Recent

Author Topic: Can't cast Tpanel to TwinControl  (Read 1488 times)

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1565
    • Lebeau Software
Re: Can't cast Tpanel to TwinControl
« Reply #15 on: September 05, 2025, 06:59:55 pm »
Sender @$00007F97ED561210 = TLabel( FALIGNMENT: TALEFTJUSTIFY;  FFOCUSCONTROL: nil;  FOPTIMALFILL: False;

Your event handler is being triggered by a TLabel, which is derived from TGraphicControl not TWinControl, that is why you are getting an invalid typecast error at runtime.

it does not change the facts that the compiler in their case must be inserting a Type check when clearly the coder didn't specify that

Yes, it can, and this is undocumented behavior. See:

https://forum.lazarus.freepascal.org/index.php?topic=58944.msg486254
https://forum.lazarus.freepascal.org/index.php/topic,64034.0.html
https://gitlab.com/freepascal.org/fpc/source/-/issues/39644

So, the expression TwinControl(sender).tag silently becomes (sender as TwinControl).tag if the -CR option is enabled, which fails if the Sender is not a TWinControl descendant, such as TLabel.

You can use the {$OBJECTCHECKS OFF} directive to disable this behavior, if needed, eg:

Code: Pascal  [Select][+][-]
  1. {$PUSH}{$OBJECTCHECKS OFF}
  2. i:=TwinControl(sender).tag;
  3. {$POP}
  4.  
« Last Edit: September 05, 2025, 07:15:45 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Thaddy

  • Hero Member
  • *****
  • Posts: 18306
  • Here stood a man who saw the Elbe and jumped it.
Re: Can't cast Tpanel to TwinControl
« Reply #16 on: September 05, 2025, 07:13:53 pm »
Note that {$objectchecks on/off} is a local define and can be used with {$push}/{$pop} to just turn it off or on for particular pieces of code. The default is still... OFF.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Bart

  • Hero Member
  • *****
  • Posts: 5612
    • Bart en Mariska's Webstek
Re: Can't cast Tpanel to TwinControl
« Reply #17 on: September 05, 2025, 07:15:20 pm »
Yes, it can, and this is undocumented behavior. This is what I documented in Indy's source code when I learned of the issue:

Code: Pascal  [Select][+][-]
  1. // In FreePascal, if the -CR compiler option (Verify object method call validity) is enabled,
  2. // the compiler emits code to make class methods raise an error if their Self pointer is nil
  3. // (this is documented behavior), BUT the compiler will ALSO silently change object hard-casts
  4. // into the 'as' operator (this is undocumented behavior!).  This change breaks any place that
  5. // Indy uses Accessor Classes to reach protected class members across unit boundaries.
  6. ...
  7.  

You can use class helpers to overcome this, see my recent changes to win32 widgetset code.

Bart

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1565
    • Lebeau Software
Re: Can't cast Tpanel to TwinControl
« Reply #18 on: September 05, 2025, 07:20:10 pm »
You can use class helpers to overcome this, see my recent changes to win32 widgetset code.

Do you have a link to that change? Or at least an example you can post here so I/people don't have to hunt for it?

In any case, Indy still supports older compilers that don't have class helpers, so this is not really an option for me.  But maybe it can help someone else.
« Last Edit: September 05, 2025, 07:23:57 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Bart

  • Hero Member
  • *****
  • Posts: 5612
    • Bart en Mariska's Webstek
Re: Can't cast Tpanel to TwinControl
« Reply #19 on: September 06, 2025, 12:38:00 pm »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1565
    • Lebeau Software
Re: Can't cast Tpanel to TwinControl
« Reply #20 on: September 07, 2025, 04:54:53 am »
Oh ok, thanks. I'll consider it for a future release of Indy. Right now, there are only a handful of access types being used, so the {$PUSH}{$OBJECTCHECKS OFF}...{$POP} workaround is sufficient for now.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

Bart

  • Hero Member
  • *****
  • Posts: 5612
    • Bart en Mariska's Webstek
Re: Can't cast Tpanel to TwinControl
« Reply #21 on: September 07, 2025, 10:12:14 pm »
Note that, with higher levels of optimization, the compiler may decide to re-order the fields of a class, in which case the access hack may stop working.

Bart

Thaddy

  • Hero Member
  • *****
  • Posts: 18306
  • Here stood a man who saw the Elbe and jumped it.
Re: Can't cast Tpanel to TwinControl
« Reply #22 on: September 08, 2025, 06:53:05 am »
@Bart
@Remy Lebeau

And that can be mitigated with {$optimization orderfields-} or {$optimization NoOrderFields} in the same {$push}{$pop}block or around the class declaration that should be prevented from field reordering.
Afaik Delphi does not support this out of the box, although llvm can perform this as a post-compile optimization.
That also means that on the llvm back end it has no issues - within the same code - since it is post-compile.

It is documented only for optimization level4
https://wiki.freepascal.org/Optimization#Optimization_Switches
« Last Edit: September 08, 2025, 07:19:49 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

 

TinyPortal © 2005-2018