Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2008-07

The usage of Include() doesn't work any more in 2.3.1

17 messages · 9 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

-------------------------  snip  --------------------------
 Include(WindowAttributes, waStayOnTop);  // <== doesn't compile with FPC 2.3.1
 WindowAttributes:=WindowAttributes +[waStayOnTop];  // <== this does
-------------------------  end  --------------------------

As far as I understood, the above two lines should do exactly the same thing and I have been using Include() since Delphi 5 days and FPC 2.0.2. Now in FPC 2.3.1 it doesn't work any more. I get the following error.

-------------------------------------------------- fpc @extrafpc.cfg test.lpr
Free Pascal Compiler version 2.3.1 [2008/06/02] for i386 Copyright (c) 1993-2008 by Florian Klaempfl
Target OS: Linux for i386
Compiling test.lpr
Compiling frm_main.pas
Compiling commands.pas
Compiling frm_splashscreen.pas
frm_splashscreen.pas(75,40) Error: Can't take the address of constant expressions
frm_splashscreen.pas(125) Fatal: There were 1 errors compiling module, stopping Fatal: Compilation aborted
Error: /opt/fpc_svn/bin/ppc386 returned an error exitcode (normal if you did not specify a source file to be compiled)
--------------------------------------------------

It compiles without issues under FPC 2.2.3 and prior. What is wrong with using Include() to add to a set? I do it all the time, plus WindowAttribute is a read/write property, unlike the compiler error in 2.0.4 where you could use Include() with a read-only property. Is this not a regression bug in FPC 2.3.1 maybe?

WindowAttributes are defined as follows:

...
  property WindowAttributes: TWindowAttributes read FWindowAttributes
write FWindowAttributes;
...

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Micha Nelissen
to Graeme Geldenhuys
Graeme Geldenhuys wrote 6 lines
WindowAttributes are defined as follows: ... property WindowAttributes: TWindowAttributes read FWindowAttributes write FWindowAttributes; ...

It's the same thing as mentioned before, FPC now guarantees you can change that into GetWindowAttributes function. If this is the case, then you can't take the address anymore of a variable, because that doesn't exist. Include() "implementation" takes the address, then modifies it to add to it.

Micha

Reply by email

Marc Weustink
to Graeme Geldenhuys: ------------------------- snip -------------------------- Include(WindowAttributes,…
Graeme Geldenhuys wrote 12 lines
Hi, ------------------------- snip -------------------------- Include(WindowAttributes, waStayOnTop); // <== doesn't compile with FPC 2.3.1 WindowAttributes:=WindowAttributes +[waStayOnTop]; // <== this does ------------------------- end -------------------------- As far as I understood, the above two lines should do exactly the same thing and I have been using Include() since Delphi 5 days and FPC 2.0.2. Now in FPC 2.3.1 it doesn't work any more. I get the following error.

You cannot pas properties in var parameters. (Imagine WindowAttributes had a Getter and didn't read directly from FWindowAttributes)

Marc

Reply by email

Daniël Mantione
to Graeme Geldenhuys: ------------------------- snip -------------------------- Include(WindowAttributes,…

Op Wed, 16 Jul 2008, schreef Graeme Geldenhuys:

Show quoted text 5 lines
It compiles without issues under FPC 2.2.3 and prior. What is wrong with using Include() to add to a set? I do it all the time, plus WindowAttribute is a read/write property, unlike the compiler error in 2.0.4 where you could use Include() with a read-only property. Is this not a regression bug in FPC 2.3.1 maybe?

2.3 prevents you form taking the address of a property, because that way you can read/write its value directly, circumventing the getter/setter. So you cannot use the @ operator, but neither can you pass properties to var parameters. Include is an internal procedure that calls an rtl function that receives the set as a "var" parameter, preventing include to work.

I think there can be two visions here:
- Include is not a real procedure, so this internal implementation detail should be hidden and this can/should be allowed; the

   compiler internally should convert it into set:=set+[member].

- While include is not a real procedure, its set parameter is clearly defined as "var". Passing properties to var parameters is not allowed, so it should not be allowed for include either.

Daniël

Reply by email

Daniël Mantione
to Daniël Mantione

Op Wed, 16 Jul 2008, schreef Daniël Mantione:

Show quoted text 13 lines
2.3 prevents you form taking the address of a property, because that way you can read/write its value directly, circumventing the getter/setter. So you cannot use the @ operator, but neither can you pass properties to var parameters. Include is an internal procedure that calls an rtl function that receives the set as a "var" parameter, preventing include to work. I think there can be two visions here: - Include is not a real procedure, so this internal implementation detail should be hidden and this can/should be allowed; the compiler internally should convert it into set:=set+[member]. - While include is not a real procedure, its set parameter is clearly defined as "var". Passing properties to var parameters is not allowed, so it should not be allowed for include either.

I forgot: The fact that 2.2 allows it does not mean 2.2 will generate correct code! Your getter/setter will be bypassed with 2.2 if you use include, that is why 2.3 prevents the generation of incorrect code.

Daniël

Reply by email

Graeme Geldenhuys
to Daniël Mantione: Op Wed, 16 Jul 2008, schreef Graeme Geldenhuys: 2.3 prevents you form taking the address…
Daniël Mantione wrote
I think there can be two visions here: - Include is not a real procedure, so this internal implementation detail should be hidden and this can/should be allowed; the compiler internally should convert it into set:=set+[member].

I think this would be ideal. Using Include() is much cleaner than set := set + [member]. And yes I understand that as it was implement, you could circumvent the getter/setter, but I believe it's something the compiler must handle correctly.

It's easy for me (from a developers point of view <wink>) to say, but I think that it's up to the compiler to resolve the 's not the job of the developer to change all existing code. Surely the compiler must be able to detect if set is a property or field variable. If it's a property, resolve the call to set := set + [member]

As it stands now, FPC 2.3.1 is going to break a LOT of code. Yes I know it was maybe a unsafe way of using Include(), but surely the compiler can handle it better. Thoughts?

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Michael Schnell
to Daniël Mantione: Op Wed, 16 Jul 2008, schreef Graeme Geldenhuys: 2.3 prevents you form taking the address…
Show quoted text 6 lines
2.3 prevents you form taking the address of a property, because that way you can read/write its value directly, circumventing the getter/setter. So you cannot use the @ operator, but neither can you pass properties to var parameters. Include is an internal procedure that calls an rtl function that receives the set as a "var" parameter, preventing include to work.

While this is obvious and of course using the address of a property should issue an error message, it seems desirable id a way is provided to allow using it in case that there is no getter or setter method. As this is defined in the interface of the component's unit, the calling code _does_ know about that fact. (Of course it's bad style as updating the called component will brake the caller's code and a Warning would be appropriate.)

-Michael

Reply by email

Daniël Mantione
to Graeme Geldenhuys: On Wed, Jul 16, 2008 at 9:40 AM, Daniël Mantione I think this would be ideal. Using…

Op Wed, 16 Jul 2008, schreef Graeme Geldenhuys:

Show quoted text 18 lines
On Wed, Jul 16, 2008 at 9:40 AM, Daniël Mantione wrote: > I think there can be two visions here: > - Include is not a real procedure, so this internal implementation detail > should be hidden and this can/should be allowed; the > compiler internally should convert it into set:=set+[member]. I think this would be ideal. Using Include() is much cleaner than set := set + [member]. And yes I understand that as it was implement, you could circumvent the getter/setter, but I believe it's something the compiler must handle correctly. It's easy for me (from a developers point of view <wink>) to say, but I think that it's up to the compiler to resolve the issue at hand. It's not the job of the developer to change all existing code. Surely the compiler must be able to detect if set is a property or field variable. If it's a property, resolve the call to set := set + [member]

This is argumentation for transparantly calling any procedure; it does not hold as an argument to handle it transparently for "include" only.

As it stands now, FPC 2.3.1 is going to break a LOT of code. Yes I know it was maybe a unsafe way of using Include(), but surely the compiler can handle it better. Thoughts?

We are aware it breaks a lot of code, and the fact that "include" is also affected does not change this, it is just a procedure that has a var parameter. Any procedure that passes properties to var parameters is affected.

The reason 2.2 still accepts it is that while the old behaviour is incorrect, many code may appear to work correctly and we do not want to break it during a stable series.

Daniël

Reply by email

Jonas Maebe
to Graeme Geldenhuys: On Wed, Jul 16, 2008 at 9:40 AM, Daniël Mantione I think this would be ideal. Using…
Graeme Geldenhuys wrote 12 lines
On Wed, Jul 16, 2008 at 9:40 AM, Daniël Mantione wrote: > I think there can be two visions here: > - Include is not a real procedure, so this internal implementation > detail > should be hidden and this can/should be allowed; the > compiler internally should convert it into set:=set+[member]. I think this would be ideal. Using Include() is much cleaner than set := set + [member]. And yes I understand that as it was implement, you could circumvent the getter/setter, but I believe it's something the compiler must handle correctly.

Adding such exceptions complicates both the compiler sources (special cases have to be added for particular constructs in particular circumstances) and the language ("x is not allowed, except in cases a, b and c"). Over time, such exceptions (even if initially added for convenience reasons) actually make things harder rather than easier for most developers, because they keep adding up and you create a completely inconsistent set of rules.

The reason is that you end up in a situation where people have to be aware which routines are compiler-internal and thus can be magically changed to do "the right thing", and which are plain rtl routines which abide by the normal language rules (other exampleq would be inc/ dec). Such differences in behaviour actually already exist nowadays, e.g. regarding overloading, causing confusion: http://bugs.freepascal.org/view.php?id=8399

Jonas

Reply by email

Graeme Geldenhuys
to Jonas Maebe

2008/7/16 Jonas Maebe :

Show quoted text 19 lines
> > I think this would be ideal. Using Include() is much cleaner than set > := set + [member]. And yes I understand that as it was implement, you > could circumvent the getter/setter, but I believe it's something the > compiler must handle correctly. Adding such exceptions complicates both the compiler sources (special cases have to be added for particular constructs in particular circumstances) and the language ("x is not allowed, except in cases a, b and c"). Over time, such exceptions (even if initially added for convenience reasons) actually make things harder rather than easier for most developers, because they keep adding up and you create a completely inconsistent set of rules. The reason is that you end up in a situation where people have to be aware which routines are compiler-internal and thus can be magically changed to do "the right thing", and which are plain rtl routines which abide by the normal language rules (other exampleq would be inc/dec). Such differences in behaviour actually already exist nowadays, e.g. regarding overloading, causing confusion: http://bugs.freepascal.org/view.php?id=8399

OK, I understand you point over the long term. So would the following still be okay?

  set += [member];

Not that I ever use the C style operators like '+=', but it does act as nice shorthand for code - replacing the need for Include().

BTW:
Is C style operator '+=' available by default in compiler mode objfpc? Or must I explicitly add -Sc ?

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email

Martin Friebe
to Jonas Maebe: Adding such exceptions complicates both the compiler sources (special cases have to be…

Hi,

just to add another opinion. Personally, I would thing that it was nice to allow (write-able) Properties to any var-param (even out-param). Write-able include properties with a setter-procedure.

IMHO the way it could be done would be for the compiler to create a temporary variable. This could be passed in as var/out-param, and then be assigned to the property, using the proper setter-procedure.

I do of course understand, that this is extra work on the compiler. And I can not judge if it has enough value for anyone to implement it.

Best Regards
Martin

Jonas Maebe wrote 36 lines
On 16 Jul 2008, at 10:01, Graeme Geldenhuys wrote: > On Wed, Jul 16, 2008 at 9:40 AM, Daniël Mantione > wrote: >> I think there can be two visions here: >> - Include is not a real procedure, so this internal implementation >> detail >> should be hidden and this can/should be allowed; the >> compiler internally should convert it into set:=set+[member]. > > I think this would be ideal. Using Include() is much cleaner than set > := set + [member]. And yes I understand that as it was implement, you > could circumvent the getter/setter, but I believe it's something the > compiler must handle correctly. Adding such exceptions complicates both the compiler sources (special cases have to be added for particular constructs in particular circumstances) and the language ("x is not allowed, except in cases a, b and c"). Over time, such exceptions (even if initially added for convenience reasons) actually make things harder rather than easier for most developers, because they keep adding up and you create a completely inconsistent set of rules. The reason is that you end up in a situation where people have to be aware which routines are compiler-internal and thus can be magically changed to do "the right thing", and which are plain rtl routines which abide by the normal language rules (other exampleq would be inc/dec). Such differences in behaviour actually already exist nowadays, e.g. regarding overloading, causing confusion: http://bugs.freepascal.org/view.php?id=8399 Jonas_______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Peter Vreman
Show quoted text 22 lines
On Wed, Jul 16, 2008 at 9:40 AM, Daniël Mantione wrote: > I think there can be two visions here: > - Include is not a real procedure, so this internal implementation detail > should be hidden and this can/should be allowed; the > compiler internally should convert it into set:=set+[member]. I think this would be ideal. Using Include() is much cleaner than set := set + [member]. And yes I understand that as it was implement, you could circumvent the getter/setter, but I believe it's something the compiler must handle correctly. It's easy for me (from a developers point of view <wink>) to say, but I think that it's up to the compiler to resolve the issue at hand. It's not the job of the developer to change all existing code. Surely the compiler must be able to detect if set is a property or field variable. If it's a property, resolve the call to set := set + [member] As it stands now, FPC 2.3.1 is going to break a LOT of code. Yes I know it was maybe a unsafe way of using Include(), but surely the compiler can handle it better. Thoughts?

At least the error message can be improved.

Additional we can maybe introduce a new switch and reduce the error to a warning in case the property is a varaible only and not a procedure.

Peter

Reply by email

Daniël Mantione
to Ales Katona

Op Wed, 16 Jul 2008, schreef Ales Katona:

I think this is also same in Delphi, but I agree that passing pure properties (without getter/setter) to var should possibly be reduced to warning or even hint.

This was discussed before and rejected.

The reason is that a change in implementation of the property should not hav any effect on code that uses of the property.

I.e. a programmer that exposes a variable by means of a property wants to have the option of introducing getters/setters later, otherwise he would have used a public variable. Therefore any code using properties has to be "ready" for future getter/setters.

Daniël

Reply by email

Jonas Maebe
to Graeme Geldenhuys: 2008/7/16 Jonas Maebe : OK, I understand you point over the long term. So would the…
Graeme Geldenhuys wrote 7 lines
OK, I understand you point over the long term. So would the following still be okay? set += [member]; Not that I ever use the C style operators like '+=', but it does act as nice shorthand for code - replacing the need for Include().
It should work fine, as x+=y is really just a notation shorthand for
x:=x+y and is not treated specially in any way by the compiler afaik.
BTW: Is C style operator '+=' available by default in compiler mode objfpc? Or must I explicitly add -Sc ?

You have to use -Sc.

Jonas

Reply by email

Jonas Maebe
to Martin Friebe: just to add another opinion. Personally, I would thing that it was nice to allow…
Martin Friebe wrote
IMHO the way it could be done would be for the compiler to create a temporary variable. This could be passed in as var/out-param, and then be assigned to the property, using the proper setter-procedure.

That results in semantics than a var/out parameter, because updates to a var/out parameter are expected to be immediately globally visible, while in this case they would only be visible after the callee has returned. You'd need something like a "copyback" parameter type for this (which then indeed could also be used with properties as opposed to only with regular fields/variables.

Jonas

Reply by email

Graeme Geldenhuys
to Jonas Maebe: It should work fine, as x+=y is really just a notation shorthand for x:=x+y and is not…
Jonas Maebe wrote 10 lines
> OK, I understand you point over the long term. So would the following > still be okay? > > set += [member]; > > Not that I ever use the C style operators like '+=', but it does act > as nice shorthand for code - replacing the need for Include(). It should work fine, as x+=y is really just a notation shorthand for x:=x+y and is not treated specially in any way by the compiler afaik.

You would have thought that, but surprise, surprise.... it doesn't!!

  WindowAttributes += [waStayOnTop];

Gives me the following error:
Error: Variable identifier expected

Regards,
- Graeme -

_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/

Reply by email