[SOLVED] FPC trunk: Existing code is broken about explicit class casting lazarus / 64-FPC development ---------------------------------------------------------------------- abouchez · 2022-04-01 08:53 Sometimes, we have a class defined as such in an unit: 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 TSomeClass = classprotected  procedure SomeProtectedMethod;end; TChildClass = class(TSomeClass);and in another unit, we want to run the SomeProtectedMethod. What we could do for ever is to create a local "hook" class: 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 TSomeClassHook  = class(TSomeClass);...  if obj is TSomeClass then     TSomeClassHook(obj).SomeProtectedMethod; It worked well, because of the forced typecast. But if obj is of type TChildClass, now FPC trunk complains at runtime. So I suspect, the trunk compiler add a runtime check to ensure that TSomeClassHook(obj) is actually a TSomeClassHook - which is not the case of course. In practice, now above code seems to be compiled as: 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 TSomeClassHook  = class(TSomeClass);...  if obj is TSomeClass then     (obj as TSomeClassHook).SomeProtectedMethod;which is breaking existing code. What should I do? ---------------------------------------------------------------------- abouchez · 2022-04-01 08:54 See https://synopse.info/forum/viewtopic.php?pid=37009#p37009 as the problem description in the wild. And https://github.com/synopse/mORMot2/commit/aa341c64 as current workaround. ---------------------------------------------------------------------- abouchez · 2022-04-01 08:56 I guess the following won't help: 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 TSomeClassHook  = class(TSomeClass);...  if obj is TSomeClass then     TSomeClassHook(pointer(obj)).SomeProtectedMethod; ---------------------------------------------------------------------- PascalDragon · 2022-04-01 13:48 Please provide a full, self contained example that demonstrates the issue. The following code works correctly in both FPC 3.2.2 and main and will only trigger the mentioned error when object checks (parameter -CR or directive $ObjectChecks) are enabled (as that is its purpose): 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 program thook; {$mode objfpc} uses  sysutils, uhook; type  TSomeClassHook = class(TSomeClass); var  obj: TObject;begin  obj := TChildClass.Create;  try    if obj is TSomeClass then      TSomeClassHook(obj).SomeProtectedMethod;  finally    obj.Free;  end;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 uhook; {$mode objfpc}{$H+} interface type  TSomeClass = class  protected    procedure SomeProtectedMethod;  end;   TChildClass = class(TSomeClass); implementation procedure TSomeClass.SomeProtectedMethod;begin  Writeln('I''m protected');end; end. ---------------------------------------------------------------------- abouchez · 2022-04-01 16:40 It was in Delphi mode, in only a single computer... perhaps the user enabled object checks in the project options. I didn't know about {$OBJECTCHECKS ON}. I will force {$OBJECTCHECKS OFF} in all units of the framework, and wait for report. ---------------------------------------------------------------------- dcoun · 2022-04-02 06:42 Reading the documentation (https://www.freepascal.org/docs- html/prog/progsu57.html): Quote1.2.57 $OBJECTCHECKS : Check Object This boolean switch determines whether code to test the SELF pointer is inserted in methods. By default it is OFF. For example: {$OBJECTCHECKS ON} If the SELF pointer is NIL a run-time error 210 (range check) will be generated. This switch is also activated by the -CR command line option. To be honest, this feature is not expected when reading the documentation. ---------------------------------------------------------------------- dcoun · 2022-04-02 10:42 In https://www.freepascal.org/docs-html/user/usersu15.htm the -CR option is described: Quote -CR     Generate checks when calling methods to verify if the virtual method table for that object is valid. -CR is the same thing with {$OBJECTCHECKS ON} or subpart of {$OBJECTCHECKS ON} ? ---------------------------------------------------------------------- PascalDragon · 2022-04-02 19:18 Quote from: dcoun on April 02, 2022, 08:42:49 amReading the documentation (https://www.freepascal.org/docs- html/prog/progsu57.html): Quote1.2.57 $OBJECTCHECKS : Check Object This boolean switch determines whether code to test the SELF pointer is inserted in methods. By default it is OFF. For example: {$OBJECTCHECKS ON} If the SELF pointer is NIL a run-time error 210 (range check) will be generated. This switch is also activated by the -CR command line option. To be honest, this feature is not expected when reading the documentation. Please file a bug report against the documentation. Quote from: dcoun on April 02, 2022, 12:42:31 pmIn https://www.freepascal.org/docs-html/user/usersu15.htm the -CR option is described: Quote -CR     Generate checks when calling methods to verify if the virtual method table for that object is valid. -CR is the same thing with {$OBJECTCHECKS ON} or subpart of {$OBJECTCHECKS ON} ? -CR enables $OBJECTCHECKS as well as $RANGECHECKS. ---------------------------------------------------------------------- dcoun · 2022-04-02 19:42 Thanks a lot. The issue is created: https://gitlab.com/freepascal.org/fpc/source/-/issues/39644 ---------------------------------------------------------------------- abouchez · 2022-04-04 06:18 I confirm the -CR switch was enabled on this computer. As a workaround, I am adding {$OBJECTCHECKS OFF} to every unit of mORMot. The documentation is indeed a bit unprecise about this function. ---------------------------------------------------------------------- af0815 · 2022-04-04 06:42 BTW: -Cr (Range) and -CR (Verify method calls) are at debugtime normal enabled. Edit: Is $OBJECTCHECKS unitlocal, global or like $R can be procedure or expressionlevel ?! ---------------------------------------------------------------------- PascalDragon · 2022-04-04 12:04 Quote from: dcoun on April 02, 2022, 09:42:46 pmThanks a lot. The issue is created: https://gitlab.com/freepascal.org/fpc/source/-/issues/39644 Thank you. Quote from: af0815 on April 04, 2022, 08:42:15 amEdit: Is $OBJECTCHECKS unitlocal, global or like $R can be procedure or expressionlevel ?! Directives are either global (for the unit) or local (for the expression). Compiler parameters can be global for the whole compilation, but not if a unit isn't recompiled. And $OBJECTCHECKS is local. ---------------------------------------------------------------------- Remy Lebeau · 2023-07-22 21:29 A user of Indy just ran into this very same issue in the wild a few days ago: https://forum.lazarus.freepascal.org/index.php/topic,63996.msg485641.h tml#msg485641 Which I then reported here (as I didn't find this discussion yet): https://forum.lazarus.freepascal.org/index.php/topic,64034.0.html Using {$OBJECTCHECKS OFF} worked to solve the issue. Although, I decided not to apply it to entire units as a whole (as the project that was using Indy needed the checks to be on), so instead I wrapped affected call sites with {$PUSH}/{$POP}, effectively like this: Code: [Select]{$PUSH} {$OBJECTCHECKS OFF} TIdSomeClassAccess(SomeObj).DoSomethingWithProtectedMember; {$POP}