Recent

Author Topic: For variable being read after loop... Any way to get an error or warning on it?  (Read 13121 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 7622
it would be nice to have inline loop counters that go out of scope when the loop is done.

Code: Pascal  [Select][+][-]
  1. For A:Integer = 0 to Whatever do...
  2.  

Yes, as I said earlier in the thread. However it's been made clear that that's not going to happen and there'd still be issues with its hiding a similarly-named variable in outer scopes, so I consider Marco's suggestion to be the best we're going to get particularly since it's not been dismissed out of hand by Sven.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

jamie

  • Hero Member
  • *****
  • Posts: 6550
it would be nice if Code tools would allow you to create a variable in place and have it automatically inserted in the VAR list nearest without leaving the current line in the editor.

 Maybe it does that now?

Maybe Ctrl+Shift+C

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2.  
  3. var
  4.   a: Integer; // it automatically inserted in the VAR list nearest without leaving the current line in the editor
  5. begin
  6.   {Ctrl+Shift+C} a:=2;
  7. end;  
  8.  

I will try that, thank you.
The only true wisdom is knowing you know nothing

BrunoK

  • Hero Member
  • *****
  • Posts: 570
  • Retired programmer
it would be nice if Code tools would allow you to create a variable in place and have it automatically inserted in the VAR list nearest without leaving the current line in the editor.
Maybe Ctrl+Shift+C
Code: Pascal  [Select][+][-]
  1.   {Ctrl+Shift+C} a:=2;
  2. end;  
  3.  

I will try that, thank you.
Thanks both of you, I learned a new tick. :-)

Hansvb

  • Hero Member
  • *****
  • Posts: 700

DarioGL

  • New member
  • *
  • Posts: 7
Wow, it looks like i opened the pandora box with this matter!

@MarkMLI if you raise it i would trully thank you for it, as the way you will expose the matter will be much more helpful for the dev than the way i could ever do it.

Just as a side note, my dad has been programming in pascal since around '85 in HP workstations and then with borland pascal, when i exposed the matter to him he raised his hands to the air and said: "Who used the for loop variable outside of the for loop? That's something you must never do! I for sure did not do it!"

Around 80% of our pascal code is his, but there have been other collaborators which probably introduced bad practices like that in our code base.

As a temporary solution, we will try to create a regular expression to look for any for loop variable thats used after the for loop, as checking the 3814 for statements is not practical.

Thank you very much everyone for your contributions and help in clarifying the issue!

440bx

  • Hero Member
  • *****
  • Posts: 4531
Just as a side note, my dad has been programming in pascal since around '85 in HP workstations
That was about the time of the 9835 and 9845 workstations which were programmable in BASIC and Pascal. 
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

silvercoder70

  • New Member
  • *
  • Posts: 48
    • Tim Coates
I was taught NEVER to rely on the value of a control variable - this was from a lecturer that wrote compilers back in the early 90s. Of course, things can change in relation to how things are done over time. And given the example code, I recently found this (https://wiki.freepascal.org/For) ...

In relation to having a ';' immediately after do:

Make it a habit and always accompany for-loops with begin … end, leaving the option to possibly eliminate those at a later stage, prior a complete code freeze (but not right in the middle of development).


As far as the value after the for loop is concerned ...

The value of the loop variable is undefined after a loop has completed or if a loop is not executed at all. However, if the loop was terminated prematurely with an exception or a break or goto statement, the loop variable retains the value it had when the loop was exited.

from https://www.freepascal.org/docs-html/ref/refsu58.html#x168-19200013.2.4

and I would say that if it did contain the final value, that would be down to luck? And for me, this applies to any language.
P Plate on FPC | YouTube - https://www.youtube.com/@silvercoder70

Zvoni

  • Hero Member
  • *****
  • Posts: 2690
As far as the value after the for loop is concerned ...

The value of the loop variable is undefined after a loop has completed or if a loop is not executed at all. However, if the loop was terminated prematurely with an exception or a break or goto statement, the loop variable retains the value it had when the loop was exited.

from https://www.freepascal.org/docs-html/ref/refsu58.html#x168-19200013.2.4

and I would say that if it did contain the final value, that would be down to luck? And for me, this applies to any language.
If you think about how For-Loops can be used in C ("For (int i=0;i<10;i++){/* blablabl */} it's even clear, that it's local scope.

Frankly, it's weirding me out how such a discussion can garner 4 pages in this thread.

It's like buying a car, and i decide to drive on the wrong side of the road.
Hey, i don't get a warning, but if i cause a crash it's my fault, not the car's.

Don't use a For-Loop control-variable after completion of the loop. Period!
EDIT: and not even before entering the loop. Period 2!

EDIT2: The only situation i use a control-variable in multiple places is in reusing it as control-variable in a following For-Loop
« Last Edit: August 06, 2024, 02:02:48 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

alpine

  • Hero Member
  • *****
  • Posts: 1263
*snip*
and I would say that if it did contain the final value, that would be down to luck? And for me, this applies to any language.
If you think about how For-Loops can be used in C ("For (int i=0;i<10;i++){/* blablabl */} it's even clear, that it's local scope.
That's probably the most inappropriate example. The for in C is just a three statements executed in a predefined sequence (just the middle one is for continuing/escaping the loop). They'll be executed always. You can write almost anything in there, including empty statements.

The Pascal for is different. It iterates over a (sub-)range of ordinal values which (range) is predetermined once in the initialization of the loop, or even at compile time in the case of constant expressions. The compiler decides how to do it, hence the uncertainty for the final value of the control variable.

The break is the usual exception of the rule, as it is commonly used in a search patterns and the target position should be kept.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

MarkMLl

  • Hero Member
  • *****
  • Posts: 7622
If you think about how For-Loops can be used in C ("For (int i=0;i<10;i++){/* blablabl */} it's even clear, that it's local scope.

As it was in ALGOL-60, and Fortran was somewhat similar. However I'd have to check, but I think that defining the local variable like that might be an ANSI rather than a K&R think.

Quote
Frankly, it's weirding me out how such a discussion can garner 4 pages in this thread.

It got Joanna'd.

I'm afraid that I didn't help, by trying to bludgeon into her the distinction between /language/ and /implementation/.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

alpine

  • Hero Member
  • *****
  • Posts: 1263
However I'd have to check, but I think that defining the local variable like that might be an ANSI rather than a K&R think.
Definitely not K&R. It was introduced much later for convenience.

"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

MarkMLl

  • Hero Member
  • *****
  • Posts: 7622
Wow, it looks like i opened the pandora box with this matter!

@MarkMLI if you raise it i would trully thank you for it, as the way you will expose the matter will be much more helpful for the dev than the way i could ever do it.

Raised as https://gitlab.com/freepascal.org/fpc/source/-/issues/40879

I've very rarely touched the "new style" bug reporter, so would appreciate it if what I've done could be checked by anybody with an interest in this.

Dario, thanks for raising this since apart from the "sound and fury" it resulted in what looks like a workable solution from Marco.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 7622
As a temporary solution, we will try to create a regular expression to look for any for loop variable thats used after the for loop, as checking the 3814 for statements is not practical.

This is a situation where not using FORTRAN-style i-j-k names for loop control variables (and not reusing the same variable for multiple loops) can make life far easier.

Identify a for loop, change the control variable name at the point of definition, do a search-replace of the variable name (only) over the scope of the for statement, and then see if anything breaks in subsequent lines.

But for that amount of code...

My suggestion would be to watch the feature request I submitted, and if it results in a tentative fix in the development version of the compiler invest time into working out how to build it (it's really not too bad). After all, considering ISO-9001 etc., there's no rule against using a non-release version of the compiler to highlight problems in your code but reverting to a "nicely run in" older version for production compilation.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 15641
  • Censorship about opinions does not belong here.
I noticed something funny:
If you declare the loop variable as a range, the result becomes predictable, but not Delphi compatible.
Code: Pascal  [Select][+][-]
  1. {$ifdef fpc}{$mode objfpc}{$endif}{$R+}
  2. type
  3.   myRange = 0..9;
  4. var
  5.   i:myRange;
  6.   j:integer;
  7. begin
  8.   writeln('defined range');
  9.   for i := 0 to 9 do write(i:3);
  10.   writeln(i:3);
  11.   writeln('plain integer');
  12.   for j := 0 to 9 do write(j:3);
  13.   writeln(j:3);  
  14. end.
FreePascal is predictable in all modes and all optimizations to hold the last value of the range. Alas that is not the case with Delphi, but Delphi warns in both cases.
Code: Text  [Select][+][-]
  1. [dcc32 Warning] Project8.dpr(15): W1037 FOR-Loop variable 'j' may be undefined after loop
  2. [dcc32 Warning] Project8.dpr(12): W1037 FOR-Loop variable 'i' may be undefined after loop
BTW Delphi 7 already gives similar warnings. The above is from 11.3CE
Rangechecks on or off does not matter.
« Last Edit: August 07, 2024, 06:28:31 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

MarkMLl

  • Hero Member
  • *****
  • Posts: 7622
Thanks for that Thaddy, although I'm not sure I'd trust that variable without a guarantee from the compiler maintainers.

Thanks also for the observation about the Delphi warning.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018