Lazarus

Free Pascal => FPC development => Topic started by: 440bx on April 04, 2019, 07:51:12 am

Title: FPC feature request/suggestion
Post by: 440bx on April 04, 2019, 07:51:12 am
Hello,

Currently FPC supports the following:

1. var
2. out

I'd like to see a third way, specifically

3. inout

I think to lessen the burden on the developers, this feature could be implemented in two (2) stages:

1. make inout a synonym/alias for var.  This would allow a programmer to use the new keyword to make the program more "self documenting".

2. in some future release of the compiler, provide a full implementation which would entail the compiler making sure that the inout variable has been initialized before being passed as a parameter and output a warning if it has not.

Of course, if the developers do it in one shot, that would be great :)

I believe this would be a nice feature.  It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.

Thank you for reading.
Title: Re: FPC feature request/suggestion
Post by: Handoko on April 04, 2019, 09:04:29 am
I'm okay with "var" but I agree "inout" is more self documenting.
Title: Re: FPC feature request/suggestion
Post by: Thaddy on April 04, 2019, 09:10:47 am
Code: Pascal  [Select]
  1. {$macro on}{$define inout:=var}
  2. procedure test(inout value:integer);
  3. begin
  4. end;
  5. begin
  6. end.
But I find it syntax rot. The meaning of var is clear. OTOH, this macro does what you want.
Title: Re: FPC feature request/suggestion
Post by: PascalDragon on April 04, 2019, 09:14:15 am
I believe this would be a nice feature.  It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.
I see no reason to add something like this. It complicates the language and adds a new keyword with no real gain.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 04, 2019, 10:34:08 am
I believe this would be a nice feature.  It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.
I see no reason to add something like this. It complicates the language and adds a new keyword with no real gain.
Here is the reason: if the compiler knows that the variable is inout then it can emit a hint (or warning) if an uninitialized variable is passed to the function or procedure.

There is another reason too: currently the -gt compiler switch incorrectly assumes that an out parameter is not initialized by the caller.  out is very clear, it tells the compiler that the variable will be written to in the function/procedure, it says absolutely nothing about the initialization state of the variable being passed to the function/procedure.

inout would provide a way for the compiler to help the programmer write better code and, it would also justify - the currently incorrect - assumption made by the -gt switch.

Code: Pascal  [Select]
  1. {$macro on}{$define inout:=var}
  2. procedure test(inout value:integer);
  3. begin
  4. end;
  5. begin
  6. end.
But I find it syntax rot. The meaning of var is clear. OTOH, this macro does what you want.

That macro causes the compiler to give a warning if the variable being passed to the function/procedure has not been initialized ?... what version of FPC are you using ?... that's a nice macro you got.

You're always entertaining :)
Title: Re: FPC feature request/suggestion
Post by: PascalDragon on April 05, 2019, 09:18:48 am
I believe this would be a nice feature.  It would make programs that use it more self documenting and, it would also probably make future automatic translation of MS headers a bit simpler and more likely to be correct.
I see no reason to add something like this. It complicates the language and adds a new keyword with no real gain.
Here is the reason: if the compiler knows that the variable is inout then it can emit a hint (or warning) if an uninitialized variable is passed to the function or procedure.
This is done by var already. There is no reason to add a new keyword for something that already exists.

There is another reason too: currently the -gt compiler switch incorrectly assumes that an out parameter is not initialized by the caller.  out is very clear, it tells the compiler that the variable will be written to in the function/procedure, it says absolutely nothing about the initialization state of the variable being passed to the function/procedure.

inout would provide a way for the compiler to help the programmer write better code and, it would also justify - the currently incorrect - assumption made by the -gt switch.
Do you have an example for that? Cause it's a bit unclear what exactly you mean here...
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 05, 2019, 01:54:36 pm
This is done by var already. There is no reason to add a new keyword for something that already exists.
No.  It is not done by var already.

var cannot make any assumptions about the state, initialized or otherwise, of the variable being passed.  It simply tells the compiler to pass the variable by reference, that's all it does, absolutely nothing else.  var gives no information to the compiler as to the state of the variable, whether it must be initialized or not before using it is passed as a parameter.

out is the same as var with the addition that it informs the compiler that the variable will be written to in the function/procedure.   That additional information enables the compiler to emit a hint or warning if the out parameter isn't being written to.  IOW, it helps the programmer catch errors (it's nice to have a compiler's help in catching such easy to overlook details.)

The reason presented for not implementing inout isn't particularly solid (I'm being kind) because the same reason could have been used for not implementing out and constref for instance.  var already does what out and constref do (the argument you're presenting) but, in addition to that, they provide additional information to the compiler.  In the case of constref it informs the compiler that the variable, in spite of being passed by reference, is a read-only variable which enables the compiler to emit a warning or an error in the case of constref, if the programmer tries to write/modify the "constant".  It's nice to have the compiler's help to ensure the code doesn't do something that was not intended (which is what constref adds to var.)

inout would make it clear to the compiler that the variable being passed _must_ be initialized before passing it as a parameter.  This would enable the compiler to emit a hint/warning if the variable has not been initialized. IOW, the programmer is giving information to the compiler, which the compiler can use to warn the programmer he/she failed to initialize the variable.  Again, it's rather nice to have the compiler help the programmer ensure that the code is as it should be (which is why Pascal has strong typing, to help the programmer correct mistakes.)

There are good reasons why declarators such as "in", "out" and "inout" are being "synthesized" in C/C++ header declarations and, it is not because C/C++ programmers like to type.

And just for orthogonality. constref is a synonym for "in" (passing an uninitialized constref variable is rather likely to be a mistake.) out is already what its name says it is (the parameter will be modified/written to).  What's missing is a way to tell the compiler about parameters that are both in and out which var does not do, thereby letting the compiler know that the variable must be initialized before being used as a parameter _and_ written to in procedure/function.  If those two conditions are not met then, the compiler can emit a hint or a warning letting the programmer know that his/her usage of the variable is not as he/she declared it.

There is another reason too: currently the -gt compiler switch incorrectly assumes that an out parameter is not initialized by the caller.  out is very clear, it tells the compiler that the variable will be written to in the function/procedure, it says absolutely nothing about the initialization state of the variable being passed to the function/procedure.

inout would provide a way for the compiler to help the programmer write better code and, it would also justify - the currently incorrect - assumption made by the -gt switch.
Do you have an example for that? Cause it's a bit unclear what exactly you mean here...

There is an entire thread on the subject http://forum.lazarus.freepascal.org/index.php/topic,41857.0.html (http://forum.lazarus.freepascal.org/index.php/topic,41857.0.html)  -gt assumes that an out parameter has _not_ been initialized (by simply trashing it upon entry) an assumption which is completely unwarranted and incorrect, not to mention that it's supposed to trash local variables not parameters.   At least if there was an inout keyword, -gt could justify its behavior by noting that the programmer didn't specify the variable was initialized by specifying inout.

Title: Re: FPC feature request/suggestion
Post by: marcov on April 05, 2019, 02:08:09 pm
Even if that is true (which is only so for older code), this can be handled with local switches so that if you use a VAR parameter under that define, the procedure signature gets the correct meaning of VAR for errorhandling.

I don't see ANY reason to make this yet another DIY incompatible syntax.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 05, 2019, 02:18:21 pm
Even if that is true (which is only so for older code), this can be handled with local switches so that if you use a VAR parameter under that define, the procedure signature gets the correct meaning of VAR for errorhandling.
I'm not seeing clearly what you mean there.  Can you give an example ?

I don't see ANY reason to make this yet another DIY incompatible syntax.
What would inout it be incompatible with ?   or are you thinking about something else ?
Title: Re: FPC feature request/suggestion
Post by: marcov on April 05, 2019, 03:59:41 pm
Even if that is true (which is only so for older code), this can be handled with local switches so that if you use a VAR parameter under that define, the procedure signature gets the correct meaning of VAR for errorhandling.
I'm not seeing clearly what you mean there.  Can you give an example ?

Code: [Select]
{$someswitchVAR VARISINOUT}

procedure xx (var yy:zz); // this signature gets mandatory in and output attributes for the static analyser.

Quote
I don't see ANY reason to make this yet another DIY incompatible syntax.
What would inout it be incompatible with ?   or are you thinking about something else ?

Delphi, $mode delphi, but more importantly I don't see the point and a language addition is an important thing.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 05, 2019, 05:01:32 pm
Code: [Select]
{$someswitchVAR VARISINOUT}

procedure xx (var yy:zz); // this signature gets mandatory in and output attributes for the static analyser.
are you suggesting changing the semantics of the var keyword by using a switch to turn into inout ?  A var is mandatory but, it doesn't tell the compiler anything about whether or not the variable should be initialized before passing it.  Adding semantics to "var" could definitely cause a lot of incompatibilities.  "var" should be left alone.

The point is to give more information to the compiler so the compiler can help the programmer ensure that the variable is used as it is intended. The cases are, 1. initialized and written-to - no way to tell the compiler at this time, 2. written-to, may or may not be initialized - done by out (a correct implementation, that is) and, 3. read-only, which implies it has been initialized, done by constref.

inout would complete the set of possibilities (case 1.) and warn when the programmer is passing a variable that has inadvertently not been initialized.  Currently the compiler cannot do that because it doesn't have enough information to do it.  That's what inout does. 


I don't see ANY reason to make this yet another DIY incompatible syntax.

What would inout it be incompatible with ?   or are you thinking about something else ?

Delphi, $mode delphi, but more importantly I don't see the point and a language addition is an important thing.
Don't include it in $mode Delphi.  It certainly wouldn't be the first time FPC has a feature that Delphi doesn't and, here is the point: inout is simply a mechanism for the programmer to inform the compiler that a variable should have been initialized before passing it as a parameter and that the variable's value will be changed in the called function/procedure.  Given that information the compiler can let the programmer know that he/she may have failed to initialize the variable before passing it (which neither var nor out are sufficient to determine that omission) and warn the programmer if he/she may have failed to set a value in the function/procedure (which var cannot do but out can - which is the whole reason to have added "out" to the language, it's its reason to exist.)  "inout" simply completes the set of possibilities.   I presume you can see the point now.

I agree that a language addition is an important thing, particularly those additions that help the compiler catch errors at compile time instead of runtime (such as inout).  A feature that often saves a lot of time to the programmer.

Title: Re: FPC feature request/suggestion
Post by: Kays on April 05, 2019, 05:38:45 pm
[…] 3. inout […]
And I'd like to have the modifier
Code: Pascal  [Select]
  1. noInNoOut
a parameter you can't read from, nor write to.
Title: Re: FPC feature request/suggestion
Post by: marcov on April 05, 2019, 07:33:48 pm
Code: [Select]
{$someswitchVAR VARISINOUT}

procedure xx (var yy:zz); // this signature gets mandatory in and output attributes for the static analyser.
are you suggesting changing the semantics of the var keyword by using a switch to turn into inout ?  A var is mandatory but, it doesn't tell the compiler anything about whether or not the variable should be initialized before passing it. 

"VAR" is a token for read/write.  If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.

Quote from: kay
noInNoOut

Why not directly add access control lists for every token  >:D
Title: Re: FPC feature request/suggestion
Post by: ASerge on April 05, 2019, 07:52:17 pm
inout would make it clear to the compiler that the variable being passed _must_ be initialized before passing it as a parameter.  This would enable the compiler to emit a hint/warning if the variable has not been initialized.
But it already works with var:
Code: Pascal  [Select]
  1. procedure Test(var X: Integer);
  2. begin
  3.   X := 1;
  4. end;
  5.  
  6. var
  7.   Y: Integer;
  8. begin
  9.   Test(Y);
  10. end.
project1.lpr(9,9) Hint: Variable "Y" does not seem to be initialized
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 05, 2019, 08:30:50 pm
@Marco
"VAR" is a token for read/write.  If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.
var is to tell the compiler that the variable should be passed by reference.  Nothing else.  At most, it could be construed to mean that the variable will be written to, which would actually not be correct, since passing by reference is often done for performance reasons (and also to prevent stack overflows), not to tell the compiler that the variable will be modified.

out does exactly the same thing as var, that is, pass by reference but, in addition to that, it lets the compiler know that the variable will be written to, which allows the compiler to check that it is actually written to and emit an error or warning if it is not.

constref is yet another case of something that does exactly the same thing as var, which is - again - pass by reference but, in addition to that, it lets the compiler know that the variable will _not_ be written to, which allows the compiler to generate an error if an attempt to write to it is made.

inout simply adds the case where the variable being passed _must_ (not optionally but, must) be initialized (the "in" part) and written to (the "out" part), which neither var, out nor constref do.   That would allow the compiler to give a warning if the variable isn't initialized thus helping the programmer to catch errors at compile time instead of run-time.

In all three cases, the code generated is exactly the same (leaving COM out of the picture).  What changes is the information given to the compiler so the compiler can help the programmer write correct code.   It's a mechanism to provide the compiler a way to verify that a variable is used as the programmer intended, just as "out" and "constref" are.

@Serge
But it already works with var:
Code: Pascal  [Select]
  1. procedure Test(var X: Integer);
  2. begin
  3.   X := 1;
  4. end;
  5.  
  6. var
  7.   Y: Integer;
  8. begin
  9.   Test(Y);
  10. end.
project1.lpr(9,9) Hint: Variable "Y" does not seem to be initialized
You are right, it does but, it really shouldn't.  There is no implication in the keyword "var" that a variable  should have been initialized (it often isn't and that is not an error.)  It really shouldn't generate a hint for that case and, generating it only contributes to drown really important hints in a large number of hints that are of little to no value.
Title: Re: FPC feature request/suggestion
Post by: kupferstecher on April 05, 2019, 09:50:04 pm


var is to tell the compiler that the variable should be passed by reference. 
out does exactly the same thing as var, that is, pass by reference but, in addition to that, it lets the compiler know that the variable will be written to,[...]
constref is yet another case of something that does exactly the same thing as var, which is - again - pass by reference but,
Isn't that the complete set of possibilities?
constref = in
out = out
var = inout

To be honest, I don't like the naming, especially of constref. in the wiki it says its for compatibility reasons with other languages. But "var" should work there in the same way?

Something I dislike more, ist the "const" thing, it shouldn't be neccessary. The compiler should allow passing a constant value via "var"-parameter. Technically that should be possible and would simplify the language.
Edit: What I mean is: The language shouldn't be cluttered by new features. It's already hard enough to impossible to understand all the various features.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 05, 2019, 10:04:30 pm
Isn't that the complete set of possibilities?
constref = in
out = out
var = inout
No, because "var" does not imply "in" (in other words, it doesn't mean the variable is initialized) nor does it imply "out" (it may just be read).  var implies nothing.  The compiler cannot (and in the case of FPC, should not) make any assumptions as to how a "var" will be used.  In some cases, it will only be read, in other cases, only written to and in yet others cases, read and written.   All of those are a correct use of a "var".

Leaving the naming aside.  It's a desirable thing to be able to tell the compiler as much as possible about how a variable is intended to be used because by doing so, the compiler can verify the variable is used as intended.  Without that information, as in the case of "var", it can't because it doesn't have the necessary information.
Title: Re: FPC feature request/suggestion
Post by: marcov on April 05, 2019, 10:19:10 pm
@Marco
"VAR" is a token for read/write.  If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.
var is to tell the compiler that the variable should be passed by reference.

However did you come by that idea?  , it is read/write calling convention semantics.

Some minor attributes for warning delivery/suppression can be postdelivered by directive as I already demonstrated.

Yes, the a warnings-only directive is micromanaging. But even more so is inventing new syntax for it.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 05, 2019, 10:52:10 pm
@Marco
"VAR" is a token for read/write.  If for some reason you want to change semantics for warnings for some minor cases, that is the way to go.
var is to tell the compiler that the variable should be passed by reference.

However did you come by that idea?  , it is read/write calling convention semantics.
I came to that idea when reading a Pascal standards report written by "some guy" who goes by the name of Niklaus Wirth.  On page 72 of his report he writes:
Quote
In  program  11.2  none  of  the  values  in  array  g  are  altered;  i.e.
g  is  not  a  result.  Consequently  g  could  have  been  defined  as  a
value  parameter  without  affecting  the  end  result.  To  understand
why  this  was  not  done.  it  is  helpful  to  look  at  the
implementation.

A  procedure  call  allocates  a  new  area  for  each  value  parameter;
this  represents  the  local  variable.  The  current  value  of  the
actual  parameter  is  "copied"  into  this  location;  exit  from  the
procedure  simply  releases  this  storage.

If  a  parameter  is  not  used  to  transfer  a  result  of  the
procedure,  a  value  parameter  is  generally  preferred.  The
referencing  is  then  quicker,  and  one  is  protected  against
mistakenly  altering  the  data.  However  in  the  case  where a
parameter  is  of  a  structured  type  (e.g.  an  array),  one  should  be
cautious,  for  the  copying  operation  is  relatively  expensive,  and
the  amount  of  storage  needed  to  allocate  the  copy may  be  large.
Because  referencing  of  each  element  in  the  array  occurs  only
once,  it  is  desirable  to  define  the  parameter  as a  variable
parameter.

That seems to be clear.  var may be used just for performance reasons and avoid potential memory problems.  IOW, there is no implication whatsoever as to what the use of a var is going to be.  The only thing it tells the compiler is that the variable will be passed by reference and absolutely nothing about whether the variable is only read, only written or read and written.

That's where I got that "idea".

Yes, the a warnings-only directive is micromanaging. But even more so is inventing new syntax for it.
To be precise (which is a necessary characteristic when writing compilers), there is no new syntax.  There would be a new keyword which would syntactically take the place of "var", "out" and/or "constref" depending on how the programmer intends to use the variable.

That keyword would provide information to the compiler to allow it to flag potential problems it cannot identify without it.

I can't help but wonder how you allowed the "constref" and "out" "inventions".  Those two things are as useless as "inout" since, according to you, var already does everything they do.

Title: Re: FPC feature request/suggestion
Post by: marcov on April 05, 2019, 11:13:10 pm
I can't help but wonder how you allowed the "constref" and "out" "inventions". 

OUT is delphi, and I was against constref back then, and still am. I also think that should have been solved with directives rather than syntax. It would have made implementing IUnknown a lot easier.

Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 12:13:39 am
OUT is delphi,
There is nothing wrong with "out".  It gives information to the compiler which in turn allows it to warn a programmer that his/her "out" parameter has not been written to.  That's a good thing.

... and I was against constref back then, and still am. I also think that should have been solved with directives rather than syntax. It would have made implementing IUnknown a lot easier.
is keeping track of the reference count in managed types what makes you avert to "out" and "constref"  ?
Title: Re: FPC feature request/suggestion
Post by: ASerge on April 06, 2019, 01:03:36 am
You are right, it does but, it really shouldn't.
Do you want to enter a new keyword "inout" to fully reproduce the current "var" behavior, but additionally want "var" to behave differently?
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 01:50:36 am
You are right, it does but, it really shouldn't.
Do you want to enter a new keyword "inout" to fully reproduce the current "var" behavior, but additionally want "var" to behave differently?
No, definitely not.  I don't want "var" to behave any different than it does now.

All I would like to see is an "inout" keyword, that is "variation" of the "var" keyword that let's the compiler know that the variable should be initialized before being passed as a parameter and that the variable should be written to in the function/procedure.  That way the compiler can emit a warning to the programmer if the variable isn't used according to the way it's declared.

To clarify one thing, stopping the compiler from emitting a superfluous hint when an uninitialized variable is passed as a var in no way changes the semantics of var.  It only changes the way the compiler determines when to emit that hint and, to be totally precise, FPC should _not_ be emitting that hint.  That hint is not applicable.   

Title: Re: FPC feature request/suggestion
Post by: JernejL on April 06, 2019, 09:02:42 am
I like this idea, i've had in the past issues using third party code which called procedure passing some data by var but in some conditions it didn't initialize it before calling, and if compiler could warn me, that would save me 2-3 days of debugging.
 
Title: Re: FPC feature request/suggestion
Post by: marcov on April 06, 2019, 03:20:48 pm
OUT is delphi,
There is nothing wrong with "out".  It gives information to the compiler which in turn allows it to warn a programmer that his/her "out" parameter has not been written to.  That's a good thing.

It was only a note about where it came from. Btw Out parameters are dangerous if you pass the same managed type by const and by out.  e.g. x(s,s); where the first param is out, and the second const.

Quote
... and I was against constref back then, and still am. I also think that should have been solved with directives rather than syntax. It would have made implementing IUnknown a lot easier.
is keeping track of the reference count in managed types what makes you avert to "out" and "constref"  ?

I avoid constref because it is non-delphi. Maybe in time I'll use const [ref], but I now also use Delphi versions that don't have it, so that is far away, even if FPC supported it now.

I don't use out much because I simply rarely feel the need to micromanage beyond VAR, and I have been bitten by the double reference bug (and some cases I didn't cared to research into detail). I suspect it is as much that it can make it harder to debug (more implicit code).

Basically quite minor issues, but the use is IMHO even less. So I generally only use it what it was meant for: interface references.

I'm also against changing source to suppress warnings if they are not outright bugs, I rather use %H- and similar markups systems to remove warnings temporarily from the view, without changing the source.

Then, if I do bughunting sessions, I can unhide and review them, if necessary.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 05:20:10 pm
Btw Out parameters are dangerous if you pass the same managed type by const and by out.  e.g. x(s,s); where the first param is out, and the second const.
<snip>
I avoid constref because it is non-delphi.
<snip>
I don't use out much because I simply rarely feel the need to micromanage beyond VAR, and I have been bitten by the double reference bug (and some cases I didn't cared to research into detail). I suspect it is as much that it can make it harder to debug (more implicit code).
I wouldn't go as far as saying "out" parameters are dangerous, I'd say it's important for the programmer to know precisely what the compiler does.  "constref" is FPC specific but, it helps ensuring that things that should not change do not change but, you're right, being FPC specific it does causes minor inconveniences when using another Pascal compiler (in my case Delphi 2) but, in spite of that, I use it whenever applicable.

I'm a strong believer in a programmer giving as much information as possible to the compiler, that way the compiler can work for the programmer and verify that what the programmer is doing is consistent with the information the compiler has been given.  It helps overcome the characteristic that making mistakes is human.  It also often helps catching small but, important design mistakes early in the development cycle instead of catching them during system testing when making changes is usually much more laborious and prone to introduce incompatibilities with other modules.

Programmers have to work hard, their compilers should too. :)
Title: Re: FPC feature request/suggestion
Post by: marcov on April 06, 2019, 05:28:56 pm
I wouldn't go as far as saying "out" parameters are dangerous, I'd say it's important for the programmer to know precisely what the compiler does.

  "constref" is FPC specific but, it helps ensuring that things that should not change do not change but, you're right, being FPC specific it does causes minor inconveniences when using another Pascal compiler (in my case Delphi 2) but, in spite of that, I use it whenever applicable.

Afaik D2 doesn't have OUT either (D+). Not that it matters, since old Delphis are Windows/x86 only, and on Windows/x86 "CONST" generally is equal to constref. That's why constref and const [ref] came relatively late in the life of both compilers. It matters most for systems whose C/C++ ABI defines const NOT by reference.

The point is that micromanaging both (at the risk of introducing hard to debug mistakes) is simply use VAR and ignore some warnings. IOW no risk without any real downsides.

Quote
I'm a strong believer in a programmer giving as much information as possible to the compiler, that way the compiler can work for the programmer and verify that what the programmer is doing is consistent with the information the compiler has been given. 

Then CONST is usually better than constref, since that allows the compiler to decide what is most advantageous.

Quote
It helps overcome the characteristic that making mistakes is human.  It also often helps catching small but, important design mistakes early in the development cycle instead of catching them during system testing when making changes is usually much more laborious and prone to introduce incompatibilities with other modules.

My experience is the opposite. Micromanaging these things, and making unnecessary modifications increase the risk more than lower it. The risks for mistakes with later modifications also increases if you don't grasp all consequences immediately. IOW the KISS principle applies.

Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 05:35:46 pm
The risks for mistakes with later modifications also increases if you don't grasp all consequences immediately. IOW the KISS principle applies.
That reminds me what a smart guy said (his name was Einstein) "make things as simple as possible but no simpler".  I think he had point. :)
Title: Re: FPC feature request/suggestion
Post by: ASerge on April 06, 2019, 05:48:05 pm
All I would like to see is an "inout" keyword, that is "variation" of the "var" keyword that let's the compiler know that the variable should be initialized before being passed as a parameter and that the variable should be written to in the function/procedure.  That way the compiler can emit a warning to the programmer if the variable isn't used according to the way it's declared.
The compiler already knows if the variable is initialized and gives a hint. Do you want it to issue a warning for that with new syntax?
Title: Re: FPC feature request/suggestion
Post by: marcov on April 06, 2019, 06:26:55 pm
The risks for mistakes with later modifications also increases if you don't grasp all consequences immediately. IOW the KISS principle applies.
That reminds me what a smart guy said (his name was Einstein) "make things as simple as possible but no simpler".  I think he had point. :)

That remind me of "The dose makes the poison" (Latin: sola dosis facit venenum), accredited to Paracelsus.

A bit of calling convention and warning management is good. Obsessing about it a poison.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 06:28:22 pm
The compiler already knows if the variable is initialized and gives a hint. Do you want it to issue a warning for that with new syntax?
No. The problem is that there the compiler is emitting a hint for a non-initialized "var" that it really shouldn't be emitting.  Here are the cases:

1.  for a var, the compiler cannot make any assumptions as to whether the variable is initialized or not, any assumption in that regard is simply incorrect and should be fixed.  FPC is emitting a hint for an un-initialized variable.  It shouldn't be doing that since passing an uninitialized var is correct and very common. 

I also want to note that, this in no way changes any of the semantics of the "var" keyword, everything stays the same _except_ for the part of the compiler that decides when to emit or not emit a hint.   

That should be cleaned up because the hint is the result of an incorrect assumption or, being a bit "too helpful".  Changing error handling is not the same as changing the language. 

2. if there was an "inout" way of passing a variable then the compiler can emit a warning for passing an uninitialized variable because "in" tells the compiler that the variable should have been initialized (something the "var" keyword does not do) and emit a warning if the "inout" variable isn't written to in the function/procedure.

What I'm suggesting is, clean up/correct the part of the compiler that mistakenly believes that a "var" should be initialized, that's incorrect.  Everything about "var" stays the same.

Add the keyword "inout" so the compiler can emit, not a hint but, a warning because "inout" explicitly tells the compiler that the variable should have been initialized.  Given that knowledge, it can rightfully emit a warning.

The other thing it automatically cleans up is the currently incorrect behavior of the -gt switch.  That switch _assumes_ that an "out" parameter has not been initialized, which is incorrect but, that assumption would be  correct if the compiler had a way for the programmer to declare that the variable should have been initialized, because in that case, "out" should only be used when the variable is _not_ initialized since, if the variable should be initialized then the parameter should be "inout" not just "out".

It would make things clean and _precise_ which FPC is seriously lacking in its handling of parameters. 

A bit of calling convention and warning management is good. Obsessing about it a poison.
It really is a terrible thing to want things done correctly.  It's so much easier to have them all messed up.
Title: Re: FPC feature request/suggestion
Post by: ASerge on April 06, 2019, 06:48:19 pm
1.  for a var, the compiler cannot make any assumptions as to whether the variable is initialized or not, any assumption in that regard is simply incorrect and should be fixed.  FPC is emitting a hint for an un-initialized variable.  It shouldn't be doing that since passing an uninitialized var is correct and very common. 
I do not think so. In my opinion, if a variable is declared as "var", then the function can read its value, which means that it is incorrect to pass an uninitialized variable to the function. Another thing is that there are a lot of incorrectly declared functions that just migrated from the time when there was no "out" modifier. As I understand it, introducing "inout" does not solve this problem, so this argument I reject. Because if we enter "inout", in any case we will need to rewrite many functions to "inout" and replace the meaning of "var" with "out". In my opinion, it is more correct to rewrite many functions from "var" to "out" without changing the meaning of "var" and introducing new syntax.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 07:29:11 pm
I do not think so. In my opinion, if a variable is declared as "var", then the function can read its value, which means that it is incorrect to pass an uninitialized variable to the function.
No, that is incorrect.  The passage from Niklaus Wirth's Pascal report makes it very clear.  No assumptions can be made nor are applicable to the initial state of a "var" because passing by reference is often done for performance reasons and/or to avoid potential stack overflows.

"var" is limited to inform the compiler that a variable should be passed by reference.  Nothing else.  That's its definition in the Pascal language.  There is nothing else associated with "var".

Another thing is that there are a lot of incorrectly declared functions that just migrated from the time when there was no "out" modifier. As I understand it, introducing "inout" does not solve this problem, so this argument I reject. Because if we enter "inout", in any case we will need to rewrite many functions to "inout" and replace the meaning of "var" with "out". In my opinion, it is more correct to rewrite many functions from "var" to "out" without changing the meaning of "var" and introducing new syntax.
I'm glad you brought that up.  If FPC was giving the _correct_ interpretation to "var" then it wouldn't be generating all those useless hints. 

The definitions are _correct_, what is incorrect is the assumption that a "var" parameter should already be initialized.  There are countless examples of "var" being used by a function/procedure to initialize parameters, they are not incorrect in any way, there is no reason to emit a hint against them.  It simply doesn't make any sense to emit a hint against them, their purpose is to initialize the parameter.

 A hint or even a warning would be appropriate if the parameter was declared as "inout" because in that case, the programmer is telling the compiler that the variable _should_ be initialized before passing it. 

Take this simple example:
Code: Pascal  [Select]
  1. GetClientRect(Wnd, ClientRect);
FPC, inappropriately complains that ClientRect should have been initialized.  If it handled "var" _correctly_ (which it does not) it wouldn't complain about it.

Now, take an API such as
Code: Pascal  [Select]
  1. SymGetLineNext(Process : THANDLE; inout Line : IMAGEHELP_LINE)
The Line parameter should have been previously initialized by a call to  SymGetLineFromAddr64 which uses a "var" for its Line parameter.

FPC is going to complain that Line has not been initialized when it finds the call to SymGetLineFromAddr64 and complain _again_ when the call to SymGetLineNext is made.   The reason for so much complaining from FPC is because it _incorrectly_ assumes that a variable should be initialized before being passed as a "var" parameter.

Get rid of that incorrect assumption and, in some cases, hundreds of utterly useless hints go away.   Not having to deal with all those useless hints would be rather nice as, would be having a compiler that follows some of the most basic standard Pascal behavior.

Title: Re: FPC feature request/suggestion
Post by: ASerge on April 06, 2019, 07:59:03 pm
"var" is limited to inform the compiler that a variable should be passed by reference.  Nothing else.  That's its definition in the Pascal language.  There is nothing else associated with "var".
We say the same about "value parameters". These are only "value parameters" and nothing more. "Value parameters are passed by value, while variable parameters are passed by reference", but otherwise they are the same. Parameters may contain garbage, but the compiler must be silent.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 08:22:19 pm
We say the same about "value parameters". These are only "value parameters" and nothing more. "Value parameters are passed by value, while variable parameters are passed by reference", but otherwise they are the same. Parameters may contain garbage, but the compiler must be silent.
No, that is logically incorrect.

A value parameter should be read otherwise there is no reason to pass it as a parameter.  Therefore, in that case, it is absolutely correct for the compiler to emit a warning that the value parameter has not been initialized.

In the case of a "var" parameter, the parameter may be read, it may be written or read and written, therefore the compiler cannot emit a warning for it not having been initialized.  One exception to that would be, if the compiler is smart enough to determine that the "var" parameter in a function/procedure is only read and remembers that fact when a variable is passed as a parameter to the function then, in that case and only in that case, a warning/hint would be appropriate.  Very few compilers out there are that smart.

That would be a nice and useful feature though.  Obviously, that would be way too much to ask for.


HTH.
Title: Re: FPC feature request/suggestion
Post by: marcov on April 06, 2019, 08:36:53 pm
A bit of calling convention and warning management is good. Obsessing about it a poison.
It really is a terrible thing to want things done correctly.  It's so much easier to have them all messed up.

No, but *correctly* and *messed up* are horribly subjective. Moreover it is not just the "problem" (and that is already a too big word), but also your "solution", yet another incompatible extension.

Calling semantics are fixed by var, for warnings there shouldn't be any new syntax. If your API/units work with "initialized var", add a modeswitch that signals that.
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 06, 2019, 08:44:53 pm
No, but *correctly* and *messed up* are horribly subjective.
What a horrible thing to say, for a mathematician they aren't.

One thing is clear, that feature will not make it into FPC.  Logical consistency and correctness are obviously not priorities and, following standards is done when convenient.    Standards are just "ideas" anyway.
Title: Re: FPC feature request/suggestion
Post by: ASerge on April 06, 2019, 10:11:30 pm
A value parameter should be read otherwise there is no reason to pass it as a parameter. 
A var parameter should be read otherwise there is no reason to pass it as var not out.
Title: Re: FPC feature request/suggestion
Post by: marcov on April 06, 2019, 10:18:31 pm
No, but *correctly* and *messed up* are horribly subjective.
What a horrible thing to say, for a mathematician they aren't.
[/quote]

Subjective should be easy to understand for mathematicians, as it is all about a different set of matrix of weights to weight the various arguments.

Quote
One thing is clear, that feature will not make it into FPC.  Logical consistency and correctness are obviously not priorities and, following standards is done when convenient.    Standards are just "ideas" anyway.

I can't make head or tails of this text. Which Standards? Whose Logic?

Both your argument as mine are logical. You just chose to focus solely on SSA warnings, I focus solely on defining a binary interface, and handle other aspects (like said meta data for warning generation) using directives, if needed (which I also have doubts about)
Title: Re: FPC feature request/suggestion
Post by: Akira1364 on April 07, 2019, 12:47:44 am
I don't have much to say here other than, there was definitely a time when FPC did not spit out hundreds and hundreds and hundreds of completely useless "uninitialized variable" warnings, for things as trivial as SetLength.

When exactly was this added, and who exactly was advocating for it? I've never seen a single person actually say they're happy that SetLength now warns about things that are blatantly already correct. Where are the people that actually wanted this to be a thing, and why did they want it?

If you ask me it's just a whole lot of clear false positives that detract from being able to pay attention to actual problems (and make the compiler seem amateurish, even though it isn't.)
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 07, 2019, 01:26:23 am
A var parameter should be read otherwise there is no reason to pass it as var not out.
Not true.  A var parameter isn't meant to state that a parameter will be read or written, only that it is passed by reference.

You're making the same mistake the FPC developers are making, associating "var" with usage it is not associated with.


Title: Re: FPC feature request/suggestion
Post by: ASerge on April 07, 2019, 09:47:07 am
Not true.  A var parameter isn't meant to state that a parameter will be read or written, only that it is passed by reference.
Binary logic. It will either be read, then there is no point "inout", or it will not, then you need to use "out". And how the parameter is passed - by reference passed or by value is no longer important.
Title: Re: FPC feature request/suggestion
Post by: Peter H on April 07, 2019, 10:27:00 am
I think a more general solution to this problem would be a dummy initialization:

Pascal should have a specialized intrinsic variable eg "void" that is assignement compatible to anything and that represents nothing.

a := void; //This doesnt generate code, because void doesnt exist, it is a dummy
someproc(a);

For now, the problem could be solved by:

if false then a := a; //The compiler should optimize this away.
someproc(a);
 8)

This program gives only warning about unreachable code.
Even at Optimization level zero there is no code generated for the initialization.
 ;D
Code: Pascal  [Select]
  1. program Project1;
  2. var i:integer;
  3. const j=0;
  4.  
  5.  
  6. procedure someproc(var i:integer);
  7. begin
  8.  i :=i;
  9. end;
  10.  
  11. begin
  12.   if false then i :=j;
  13.   someproc(i);
  14.   readln;
  15. end.
  16.  
  17.  

Variables must ALWAYS be initialized.
At least with a dummy initialization.  8-)

Another way would be RAII.

Variables should not be declared before they can be initialized.
Declaration and initialization should be in the same statement.
So if, as an exception to the rule, a variable is declared and not initialized then it is clear that the next step will be initialization.
This approach requires inline variable declaration, O:-)
Title: Re: FPC feature request/suggestion
Post by: kupferstecher on April 07, 2019, 01:14:27 pm
I think a more general solution to this problem would be a dummy initialization:

Pascal should have a specialized intrinsic variable eg "void" that is assignement compatible to anything and that represents nothing.

a := void; //This doesnt generate code, because void doesnt exist, it is a dummy
What is it good for? (Absolutely nothing...)
You want to tell the compiler that you initialized the variable, although you didn't? What should the compiler do with this information? Remove his hint/warning? So you tell by that quer syntax you know what you are doing. Half year later you modify the code and actually use the uninitialized value. The compiler doesn't warn you, because in one moment you thought you have to trick the compiler. With a therefore created syntax feature...
Title: Re: FPC feature request/suggestion
Post by: 440bx on April 07, 2019, 01:34:35 pm
Binary logic. It will either be read, then there is no point "inout", or it will not, then you need to use "out". And how the parameter is passed - by reference passed or by value is no longer important.
Serge, the point is that whether or not the language supports "out", that doesn't change the definition of "var".  That's the mistake, implicitly (or explicitly) changing the definition of a language construct because of the existence of another.  That is conceptually incorrect.

For instance, the existence of Int64 doesn't change the definition of Int32. They are completely independent definitions.  Nothing is associated with one because of the existence of the other.

"var" is a language construct used by the programmer to tell the compiler that a variable should be passed by reference.  No more, no less regardless of the existence of any other construct such as "out" and/or "constref".

The large number of useless hints FPC emits is one of the side effects of incorrectly associating behavior that is not applicable to "var".

There is absolutely nothing wrong nor incorrect with:
Code: Pascal  [Select]
  1. function GetClientRect(Wnd: HWND; var ClientRect : TRECT) : BOOL; etc

That's perfectly valid (ignore the etc, of course.) The incorrect association that "var" should be initialized results in "hints" that are meaningless and useless. 

That said, it would be better if that function was defined as
Code: Pascal  [Select]
  1. function GetClientRect(Wnd: HWND; out ClientRect : TRECT) : BOOL; etc
because that way, the compiler is given additional information which let's it know the function will change the parameter.  In addition to that, when the little codetools window pops up, the programmer gets that information which can often be useful.

When things are done correctly they usually work very nicely.  When  things are not correct, there are often undesirable side effects and in the case of the incorrect "var" association, that side effects is a torrent of worthless hints (among others.)

Honestly, all those useless hints are a real PITA.  Take a small unit of about 6000 lines that uses the API to get its work done and, the useful hints are drowned in a morass of useless hints.  It really makes using the compiler's messages a burden.   

That incorrect "var" association quickly becomes a real time waster.

HTH.