View Issue Details

IDProjectCategoryView StatusLast Update
0022344FPCCompilerpublic2013-04-22 17:42
ReporterErn O'Malley Assigned ToJonas Maebe  
PrioritynormalSeveritycrashReproducibilityalways
Status resolvedResolutionfixed 
Fixed in Version3.0.0 
Summary0022344: Compiler generates incorrect (or no) code for function call
Description(* simple recursive routine to count characters in a file *)

program showbug ;

function countchars : INTEGER ;
var
    donewith : CHAR ;
begin
if EOF then
    countchars := 0
else
    begin
    read ( donewith ) ; countchars := 1 + countchars
    end
end ;

begin
writeln ( 1 + countchars )
end .
TagsNo tags attached.
Fixed in Revision21817
FPCOldBugId
FPCTarget
Attached Files

Relationships

related to 0024309 resolvedMichael Van Canneyt A recursive call of a function without arguments is not recognised as such. 

Activities

Jonas Maebe

2012-06-30 21:01

manager   ~0060758

You have to use countchars() to force a recursive call instead of using the current invocation's function result, or compile using TP/Delphi mode

Ern O'Malley

2012-06-30 23:26

reporter   ~0060759

In that case the LRM is wrong, as function calls are not required to have parameter lists; as demonstrated by the identical syntax in the top-level call.

More importantly, if the recursive call is syntactically correct (as a straight assignment rather than a call), it's semantically wrong because the types don't match.

The compiler should flag one or another of these errors, and not simply generate incorrect code -- this bug (and be clear, this a compiler bug, not a programmer error) has been extremely hard to track down in the large package I'm trying to port, and doubtless other examples will spring to light.

Jonas Maebe

2012-06-30 23:42

manager   ~0060760

That is how the FPC dialects work by design (using the function name as an R-value is supported, and in case of ambiguity you have to add parentheses to force a recursive call). If you don't like that, use the TP or Delphi dialects as mentioned before.

Ern O'Malley

2012-07-07 02:27

reporter   ~0060876

Last edited: 2012-07-07 02:31

Hmm. That seems to be a bit harsh. Adding parentheses is a workaround (for which, many thanks -- I didn't spot that in the LRM, hence my original remarks about syntax), but I think I'm reporting a compiler bug, so I'm slightly surprised that you consider the issue "resolved".

I'm not sure what code is being generated (I'm new to FPC and don't know how to see this) but from the value of the incorrect result, I'd guess that the address of the function "countchars" is being returned rather than the result of evaluating a recursive call.

I'd take the view that this is a type-checking failure, since the procedure "countchars" is of type "function : INTEGER" (which is stated in the LRM to be a pointer), whilst the "+" operator requires both its arguments to be INTEGER . Although I can get the effect I want using your workaround, it would have saved me a lot of debugging effort if the compiler had reported my original program as having a type error, rather than just generating code to return an incorrect and inappropriate value.

I tried your suggestion that I compile the program in Turbo or Delphi mode. In fact Turbo mode gives the same result as the default (FPC?) mode, but Delphi mode gives the expected result without adding redundant parentheses. It also gives the expected type error if I explicitly declare the function "countchars" to return an object of type "function : INTEGER".

My original program is being ported from Think Pascal, which I believe is one of the dialects which you're trying to support with FPC. In this particular case, Think Pascal (and other Macintosh Pascal dialects I've used) behave like Delphi, both syntactically and semantically, so fixing the problem is just a matter of generating the same code for recursive procedure calls in Mac Pascal mode as you do in Delphi mode.

Hope this helps.

Best Wishes from Ern O'Malley

Jonas Maebe

2012-07-07 18:25

manager   ~0060884

Last edited: 2012-07-07 18:26

I marked it as "resolved" with resolution "no change required". The reason is that the behaviour you describe is correct for FPC mode, and if you do not add any {$mode xxx} statements to your source code, then the code will be compiled in that mode.

Using the function name on the left hand side in an expression, assigns something to the function result. In FPC and ObjFPC modes, you can also use it on the right hand side to obtain the last assigned value. If none was assigned previously, the result will be undefined (in practice, it will be whatever the register/memory used as backing store for the function result variable contained previously). It does not return the address of the function (in FPC/ObjFPC modes, getting the address of a function requires using the @-operator, like in other cases when getting the address of something).

I cannot reproduce the behaviour you describe for Turbo Pascal mode. Note that it is activated using {$mode tp}, not {$mode turbo} (the compiler will give a warning if you use an invalid mode name).

MacPas mode currently indeed behaves like FPC/ObjFPC mode, which is probably an oversight by the person who implemented that mode (he is no longer active, and I've never used either Think Pascal or Metrowerks Pascal). I will change that.

In the future, if you are using a particular syntax mode, please mention that at the start when reporting a problem. Behaviour can and does differ across different syntax modes by design, obviously.

Jonas Maebe

2012-07-08 11:54

manager   ~0060898

MacPas mode now behaves the same as TP/Delphi mode in this respect.

Jonas Maebe

2012-07-09 10:04

manager   ~0060915

It seems that Mac Pascal compilers did/do allow using the name of the function result on the right hand side like a local variable, because we already had a test for that: http://svn.freepascal.org/svn/fpc/trunk/tests/test/tmacfunret.pp

Does that program compile in Think Pascal and/or Metrowerks Pascal? And does the program in the description of this bug report when compiled with those compilers nevertheless result in recursive function calls? In that case, do you have access to any formal description that says when we should generate a recursive call and when we should treat the expression as a variable access? Without such a description, we can keep changing the behaviour forever without ever getting it correct.

Adriaan van Os

2012-08-07 11:15

developer   ~0061468

Last edited: 2012-08-07 11:16

The 1973 Pascal Report by Niklaus Wirth reads in section 8.2

    A function designator specifies the activation of a function. It consists of the identifier designating the function and a list of actual parameters

    <function designator> ::= <function identifier> | <function identifier> ( <actual parameter> { ,<actual parameter> } )
    <function identifier> ::= <identifier>

and in section 11

    Within the function declaration there must be at least one assignment statement assigning a value to the function identifier. This assignment determines the result of the function. Occurrence of the function identifier in a function designator within its declaration implies recursive execution of the function.

and further in section 9.1.1

    The assignment statement serves to replace the current value of a variable by a new values specified as an expression.

    <assignment statement> ::= <variable> := <expression> | <function identifier> := <expression>


The Pascal ISO 7185:1990 standard expresses this in section 6.2.3.3 as follows

    Within an activation, an applied occurrence of a label or variable-identifier, or of a procedure identifer or function-identifier local to the block of the activation, shall denote the corresponding program-point, variable, procedure, or function, respectively, of that activation; except that the function-identifier of an assignment-statement shall, within an activation of the function denoted by that function-identifier, denote the result of that activation.


So, the conclusion can only be that a function-identifier is never considered an rvalue, but always a recursive activation, with the exception of the left-side of an assignment statement. Whether the functiion has parameters or not, is irrelevant in this context.

This is also how CW-Pascal and GPC are implemented (and what MACPAS mode should do).

If FPC modes behaves differently, this is quite remarkable and a nasty trap for experienced Pascal programmers. I don't know if this can be reverted for FPC modes. If not, a warning should be issued (for what I consider a design mistake).

Adriaan van Os

2012-08-07 11:33

developer   ~0061470

I think the tmacfunret.pp test mentioned by Jonas above, is an absurdity in the CW-Pascal compiler, that doesn't need to be reproduced in MACPAS mode.

Issue History

Date Modified Username Field Change
2012-06-30 20:43 Ern O'Malley New Issue
2012-06-30 21:01 Jonas Maebe Status new => resolved
2012-06-30 21:01 Jonas Maebe Resolution open => no change required
2012-06-30 21:01 Jonas Maebe Assigned To => Jonas Maebe
2012-06-30 21:01 Jonas Maebe Note Added: 0060758
2012-06-30 23:26 Ern O'Malley Status resolved => feedback
2012-06-30 23:26 Ern O'Malley Resolution no change required => reopened
2012-06-30 23:26 Ern O'Malley Note Added: 0060759
2012-06-30 23:42 Jonas Maebe Status feedback => resolved
2012-06-30 23:42 Jonas Maebe Resolution reopened => no change required
2012-06-30 23:42 Jonas Maebe Note Added: 0060760
2012-07-01 22:15 Ern O'Malley Status resolved => feedback
2012-07-01 22:15 Ern O'Malley Resolution no change required => reopened
2012-07-01 22:37 Jonas Maebe Status feedback => resolved
2012-07-01 22:37 Jonas Maebe Resolution reopened => no change required
2012-07-07 02:27 Ern O'Malley Status resolved => feedback
2012-07-07 02:27 Ern O'Malley Resolution no change required => reopened
2012-07-07 02:27 Ern O'Malley Note Added: 0060876
2012-07-07 02:31 Ern O'Malley Note Edited: 0060876
2012-07-07 18:25 Jonas Maebe Note Added: 0060884
2012-07-07 18:26 Jonas Maebe Note Edited: 0060884
2012-07-08 11:54 Jonas Maebe Fixed in Revision => 21817
2012-07-08 11:54 Jonas Maebe Status feedback => resolved
2012-07-08 11:54 Jonas Maebe Fixed in Version => 2.7.1
2012-07-08 11:54 Jonas Maebe Resolution reopened => fixed
2012-07-08 11:54 Jonas Maebe Note Added: 0060898
2012-07-09 10:04 Jonas Maebe Status resolved => feedback
2012-07-09 10:04 Jonas Maebe Resolution fixed => reopened
2012-07-09 10:04 Jonas Maebe Note Added: 0060915
2012-08-07 11:15 Adriaan van Os Note Added: 0061468
2012-08-07 11:16 Adriaan van Os Note Edited: 0061468
2012-08-07 11:33 Adriaan van Os Note Added: 0061470
2013-04-07 17:52 Jonas Maebe Status feedback => resolved
2013-04-07 17:52 Jonas Maebe Resolution reopened => fixed
2013-04-22 17:42 Jonas Maebe Relationship added related to 0024309