inconsistent FPC behavior in corner case lazarus / 62-General ---------------------------------------------------------------------- 440bx · 2020-02-12 01:50 Hello, Consider the following short programCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {   1 }{   2 } program TestNameResolution;{   3 }{   4 } const{   5 }   b = 1;                     // define b{   6 }{   7 } type{   8 }   T = array[1..10] of integer; // define T{   9 }{  10 }   procedure X;{  11 }   const{  12 }     b = b;                     // resolves using first const definition{  13 }{  14 }   type{  15 }     T = array[1..10] of T;     // doesn't resolve using the first type{  16 }                              // definition (it should, just as for b){  17 }   begin{  18 }   end;{  19 }{  20 } begin{  21 } end. FPC accepts, as it should, the constant definition "b = b" because b has been defined in a previous block but, it doesn't behave the same way when it resolves type definitions.  In the case of type T, it doesn't use the existing definition of T, instead it declares an "illegal expression". Just for the record, Delphi refused to compile either statement (at least it's consistent.) ---------------------------------------------------------------------- Thaddy · 2020-02-12 07:32 It is not a corner case, but borderline programming If such a pattern proves necessary put the global declarations in a separate unit, so you can qualify them. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {   2 } program TestNameResolution;{   3 } uses globs;{   9 }{  10 }   procedure X;{  11 }   const{  12 }     b = globs.b;                   // resolves {  13 }{  14 }   type{  15 }     T = array[1..10] of globs.T;     // also resolves{  17 }   begin{  18 }   end;{  19 }{  20 } begin{  21 } end.Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit globs;interface{   4 } const{   5 }   b = 1;                     // define b{   6 }{   7 } type{   8 }   T = array[1..10] of integer; // define Timplementationend.If b=b really works you may have a point, though. I would ask on the devel mailing list before posting a bug, though. There may be an explanation we overlooked. ---------------------------------------------------------------------- Bart · 2020-02-12 08:29 Quote from: Thaddy on February 12, 2020, 08:32:38 amIf b=b really works you may have a point, though. I would ask on the devel mailing list before posting a bug, though. There may be an explanation we overlooked. Delphi 7 allows that too. Bart ---------------------------------------------------------------------- Thaddy · 2020-02-12 09:37 Quote from: Bart on February 12, 2020, 09:29:33 am[Delphi 7 allows that too. Bart Both? The issue is about the array and that is refused. ---------------------------------------------------------------------- 440bx · 2020-02-12 11:54 Quote from: Thaddy on February 12, 2020, 08:32:38 amIt is not a corner case, but borderline programming That's putting it kindly... a very thin border. Quote from: Thaddy on February 12, 2020, 08:32:38 amIf b=b really works you may have a point, though. I would ask on the devel mailing list before posting a bug, though. There may be an explanation we overlooked. b = b does work and, it should work (note: I'm not saying it's good programming only that it should work), for the same reason the declaration of the T array of T should also work.  Both cases reflect the timing a type definition is added to the parser's tables. Quote from: Bart on February 12, 2020, 09:29:33 amDelphi 7 allows that too. Interesting, Delphi 2 refused both statements. ---------------------------------------------------------------------- Thaddy · 2020-02-12 12:08 Comparing to D2 is a bit gross, but if b = b works, so the array should work. I will fire up D7 to check if Bart's statement is really true for both. My guess is: not! BTW I also use D2 if size matters, but 32 bit windows is not something I regularly target. ---------------------------------------------------------------------- Bart · 2020-02-12 13:46 Borland Delphi Version 15.0 (That's D7 for you) Copyright (c) 1983,2002 Borland Software Corporation test.pas(11) Error: Type 'T' is not yet completely defined test.pas(16) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {10}type{11}  T = array[0..1] of T; Bart ---------------------------------------------------------------------- ASerge · 2020-02-12 16:21 Quote from: 440bx on February 12, 2020, 12:54:10 pmBoth cases reflect the timing a type definition is added to the parser's tables. For types, the name is included in the table immediately to allow such definitions: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TSome = class    X: TSome;  end;As a result in Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i T = array[0..1] of T; Type 'T' is not yet completely defined. ---------------------------------------------------------------------- Thaddy · 2020-02-12 16:37 Quote from: Bart on February 12, 2020, 02:46:53 pmBorland Delphi Version 15.0 (That's D7 for you) Copyright (c) 1983,2002 Borland Software Corporation test.pas(11) Error: Type 'T' is not yet completely defined test.pas(16) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {10}type{11}  T = array[0..1] of T; Bart Therefor your observation is correct. Just tested D7 too. So Delph 7 is also inconsistent. I agree with ASerge that a circular reference should not be allowed so basically the current behavior is explained sufficiently. This seems not a bug to me. ---------------------------------------------------------------------- 440bx · 2020-02-12 16:49 Quote from: ASerge on February 12, 2020, 05:21:40 pmAs a result in Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i T = array[0..1] of T; Type 'T' is not yet completely defined. But T is completely defined, just in another block, just like the constant "b".  The problem is that it added the current T type definition into the parser's tables and, because of that when searching for the definition of T (as the type of array element), it finds the incomplete definition instead of the previously defined T.  IOW, it added the current type definition too early, that caused the masking of the previous full definition of T.  In the case of the constant "b", the fact that it finds the previous definition indicates that the current definition was _not_ added to the parser's table until the definition was complete.  That prevented the previous definition of "b" from being masked away by the new one. All that said, re-using names in the same definition (such as "b" and "T") is a very poor practice so, maybe it's better that FPC does it that way even though, strictly speaking, it is "questionable". I see your point about the class definitions, you're right, for classes it does need to add the type early in the parser's table.  That's probably why it initially marks it "incomplete" and it accepts a reference to the class because unlike in a "normal" type definition, a reference to a class is just a pointer and that's all it really needs to know at that point. Quote from: Thaddy on February 12, 2020, 05:37:52 pmThis seems not a bug to me. Strictly speaking, it is incorrect.  Pascal's scope rules allow the definition of T as I posted it.  OTOH, losing the ability of creating such questionable definitions is more a blessing than anything else.  That said, if it allows it for constants then it should allow it for types too.  Either allow it or don't allow it but, not "allow sometimes" and "don't allow other times". ---------------------------------------------------------------------- Thaddy · 2020-02-12 17:30 I agree. But  there are compatibility reasons to take in account. Is this somewhere marked as a bug in Delphi? ---------------------------------------------------------------------- FPK · 2020-02-12 20:49 Type blocks needs some special handling in this case as stuff like Code: [Select]type   tc = class     owner : tc;   end; must be possible. ---------------------------------------------------------------------- Thaddy · 2020-02-12 20:56 I will trust the benevolent dictator for life.