AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Die Delphi-IDE Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt
Thema durchsuchen
Ansicht
Themen-Optionen

Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

Ein Thema von TiGü · begonnen am 7. Dez 2023 · letzter Beitrag vom 13. Feb 2024
Antwort Antwort
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#1

Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 7. Dez 2023, 16:16
Hallo zusammen,

ich bin gerade dabei Delphi 12 zu installieren und einzurichten und bin über ein Stück Code in unserer Software gestolpert, welches Probleme bereitet.
Anscheinend hat der Compiler eine Regression erfahren.
Der Original-Code mappt einen Enumerationstyp (im Beispiel unten TMyEnum ) mit weit über 256 Elementen in ein Hilfs-Record, welches ein Set of TMyEnum ersetzt (weil eine Menge nicht mehr als 256 Elemente aufnehmen kann).
Im Beispiel sind es weniger Enum-Elemente, weil es für das Problem egal ist.

Dieses Stückchen Quelltext hat im Laufe der Jahre (eher Jahrzehnte) gut funktioniert.
Ein leeres Array mit [] wird dem Record zugewiesen und per Implicit-Operator wird es intern umgewandelt.
Siehe procedure Main im unteren Beispiel.
In Delphi 11.3 funktioniert das zuweisen per Implicit-Operator sehr schön ohne Probleme.
In Delphi 12 bekomme ich im procedure TMyEnumWrapper.Create(const a: array of TMyEnum); einen ERangeError bei Auswertung des Low()/High().

Wie seht ihr das, sollte ich einen Bug im Emba Jira anlegen?

Delphi-Quellcode:
program EnumToRecordImplicitBroken;

{$APPTYPE CONSOLE}
{$R *.res}

uses
    System.SysUtils;

type
    TMyEnum = (entry_1, entry_2, entry_3, entry_4, entry_5, entry_6, entry_7, entry_8, entry_9, entry_10, entry_11, entry_12,
      entry_13, entry_14, entry_15, entry_16, entry_17, entry_18, entry_19, entry_20, entry_21, entry_22, entry_23, entry_24,
      entry_25, entry_26, entry_27, entry_28, entry_29, entry_30, entry_31, entry_32, entry_33, entry_34, entry_35, entry_36,
      entry_37, entry_38, entry_39, entry_40, entry_41, entry_42, entry_43, entry_44, entry_45, entry_46, entry_47, entry_48,
      entry_49, entry_50, entry_51, entry_52, entry_53, entry_54, entry_55, entry_56, entry_57, entry_58, entry_59, entry_60,
      entry_61, entry_62, entry_63, entry_64, entry_65, entry_66, entry_67, entry_68, entry_69, entry_70, entry_71, entry_72,
      entry_73, entry_74, entry_75, entry_76, entry_77, entry_78, entry_79, entry_80, entry_81, entry_82, entry_83, entry_84,
      entry_85, entry_86, entry_87, entry_88, entry_89, entry_90, entry_91, entry_92, entry_93, entry_94, entry_95, entry_96,
      entry_97, entry_98, entry_99, entry_100, entry_101, entry_102, entry_103, entry_104, entry_105, entry_106, entry_107,
      entry_108, entry_109, entry_110, entry_111, entry_112, entry_113, entry_114, entry_115, entry_116, entry_117, entry_118,
      entry_119, entry_120, entry_121, entry_122, entry_123, entry_124, entry_125, entry_126, entry_127, entry_128, entry_129,
      entry_130, entry_131, entry_132, entry_133, entry_134, entry_135, entry_136, entry_137, entry_138, entry_139, entry_140,
      entry_141, entry_142, entry_143, entry_144, entry_145, entry_146, entry_147, entry_148, entry_149, entry_150, entry_151,
      entry_152, entry_153, entry_154, entry_155, entry_156, entry_157, entry_158, entry_159, entry_160, entry_161, entry_162,
      entry_163, entry_164, entry_165, entry_166, entry_167, entry_168, entry_169, entry_170, entry_171, entry_172, entry_173,
      entry_174, entry_175, entry_176, entry_177, entry_178, entry_179, entry_180, entry_181, entry_182, entry_183, entry_184,
      entry_185, entry_186, entry_187, entry_188, entry_189, entry_190, entry_191, entry_192, entry_193, entry_194, entry_195,
      entry_196, entry_197, entry_198, entry_199, entry_200);

    TMyEnumWrapper = record
        FMyEnumSet: array [0 .. (Ord(High(TMyEnum)) div 32) + 1] of Cardinal;

        function ToString: string;
        procedure IndexOf(const a: TMyEnum; out Index: Integer; out Mask: Cardinal); inline;
        procedure SetItem(const a: TMyEnum); inline;

        procedure Create(); overload;
        procedure Create(const a: TMyEnum); overload;
        procedure Create(const a: array of TMyEnum); overload;

        class operator Implicit(const a: array of TMyEnum): TMyEnumWrapper; overload;
        class operator Implicit(const a: TMyEnum): TMyEnumWrapper; overload;

        class operator In (const a: TMyEnum; const b: TMyEnumWrapper): Boolean;
    end;

class operator TMyEnumWrapper.Implicit(const a: array of TMyEnum): TMyEnumWrapper;
begin
    // in Delphi 12 ist das im Local Variables Window ein "Inaccessible value" -> da fängt der Fehler schon an
    // in Delphi 11.3 steht im Local Variables Window ein "()" -> richtig und schön
    Result.Create(a);
end;

procedure TMyEnumWrapper.Create;
begin
    FillChar(Self, sizeof(TMyEnumWrapper), 0);
end;

procedure TMyEnumWrapper.Create(const a: array of TMyEnum);
var
    i: Integer;
begin
    Create();
    for i := Low(a) to High(a) do
    begin
        SetItem(a[i]);
    end;
end;

procedure TMyEnumWrapper.Create(const a: TMyEnum);
begin
    Create();
    SetItem(a);
end;

class operator TMyEnumWrapper.Implicit(const a: TMyEnum): TMyEnumWrapper;
begin
    Result.Create();
end;

class operator TMyEnumWrapper.In(const a: TMyEnum; const b: TMyEnumWrapper): Boolean;
var
    i: Integer;
    m: Cardinal;
begin
    b.IndexOf(a, i, m);
    Result := (b.FMyEnumSet[i] and (m)) <> 0;
end;

procedure TMyEnumWrapper.IndexOf(const a: TMyEnum; out Index: Integer; out Mask: Cardinal);
var
    i: Integer;
begin
    i := Ord(a);
    Index := (i div 32);
    Mask := $01 shl (i - (Index * 32)); // Maske (Bit)
end;

procedure TMyEnumWrapper.SetItem(const a: TMyEnum);
var
    i: Integer;
    m: Cardinal;
begin
    IndexOf(a, i, m);
    FMyEnumSet[i] := (FMyEnumSet[i] or m);
end;

function TMyEnumWrapper.ToString: string;
var
    i: Integer;
begin
    Result := '';

    for i := 0 to Length(self.FMyEnumSet) - 1 do
    begin
        if (Result <> '') then
            Result := Result + ', ';
        Result := Result + Ord(FMyEnumSet[i]).ToString;
    end;
end;

procedure Main;
var
    MyEnumWrapperVar: TMyEnumWrapper;

begin
    MyEnumWrapperVar := [];
    Writeln(MyEnumWrapperVar.ToString);
end;

begin
    try
        Main;
    except
        on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
    end;
    readln;

end.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.015 Beiträge
 
Delphi 12 Athens
 
#2

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 7. Dez 2023, 16:49
Wichtiger Hinweis fehlt: Passiert nur bei Target = Win64!
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 8. Dez 2023, 09:24
Ja, stimmt! Guter Hinweis.
Ich debugge meistens in der Zielplattform Win64.

Das Problem muss irgendwie mit dem Implicit-Operator zu tun haben, denn eine reine Funktion geht ohne Probleme in 64-Bit.

Delphi-Quellcode:
function Convert(const a: array of TMyEnum): TMyEnumWrapper;
begin
    Result.Create(a);
end;
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#4

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 10. Dez 2023, 05:17
Da haben sie wohl beim open array 64-bit machen ne Stelle im Compiler vergessen.
Reported: https://quality.embarcadero.com/browse/RSP-43656
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 12. Dez 2023, 14:28
Da haben sie wohl beim open array 64-bit machen ne Stelle im Compiler vergessen.
Reported: https://quality.embarcadero.com/browse/RSP-43656
Vielen lieben Dank für den vereinfachten Testfall und das reporten!

@Alle: Bitte für den RSP voten!
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.763 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 12. Dez 2023, 15:18
Abgestimmt!

Ich bin ja sowas von beunruhigt, daß die bei Embarcadero Unit Tests nicht besser machen als ich.
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 13. Dez 2023, 15:47
Hier die generierten Debug Win64 Disassembler-Views zwischen begin und end des TRec.Implicit-Operators.
Sieht schon blöd anders aus unterhalb der for-Schleife.

Delphi-Quellcode:
// Delphi 11.3
SteviesExample.dpr.20: begin
000000000042BC50 55 push rbp
000000000042BC51 4883EC10 sub rsp,$10
000000000042BC55 488BEC mov rbp,rsp
000000000042BC58 895528 mov [rbp+$28],edx
SteviesExample.dpr.24: for i := Low(values) to High(values) do
000000000042BC5B 33C0 xor eax,eax
000000000042BC5D 8B4D28 mov ecx,[rbp+$28]
000000000042BC60 894508 mov [rbp+$08],eax
000000000042BC63 394D08 cmp [rbp+$08],ecx
000000000042BC66 7F10 jnle TRec.&op_Implicit + $28
000000000042BC68 2BC8 sub ecx,eax
000000000042BC6A 83C101 add ecx,$01
SteviesExample.dpr.28: end;
000000000042BC6D 83450801 add dword ptr [rbp+$08],$01
SteviesExample.dpr.24: for i := Low(values) to High(values) do
000000000042BC71 83E901 sub ecx,$01
000000000042BC74 85C9 test ecx,ecx
000000000042BC76 75F5 jnz TRec.&op_Implicit + $1D
000000000042BC78 90 nop
SteviesExample.dpr.31: end;
000000000042BC79 8B450C mov eax,[rbp+$0c]
000000000042BC7C 488D6510 lea rsp,[rbp+$10]
000000000042BC80 5D pop rbp
000000000042BC81 C3 ret


// Delphi 12
SteviesExample.dpr.20: begin
000000000042C4C0 55 push rbp
000000000042C4C1 4883EC30 sub rsp,$30
000000000042C4C5 488BEC mov rbp,rsp
000000000042C4C8 48895548 mov [rbp+$48],rdx
SteviesExample.dpr.24: for i := Low(values) to High(values) do
000000000042C4CC 488B4548 mov rax,[rbp+$48]
000000000042C4D0 B900000080 mov ecx,$80000000
000000000042C4D5 488D0C01 lea rcx,[rcx+rax]
000000000042C4D9 BAFFFFFFFF mov edx,$ffffffff
000000000042C4DE 483BCA cmp rcx,rdx
000000000042C4E1 7605 jbe TRec.&op_Implicit + $28
000000000042C4E3 E8E8B8FDFF call @BoundErr
000000000042C4E8 33C9 xor ecx,ecx
000000000042C4EA 894D28 mov [rbp+$28],ecx
000000000042C4ED 394528 cmp [rbp+$28],eax
000000000042C4F0 7F10 jnle TRec.&op_Implicit + $42
000000000042C4F2 2BC1 sub eax,ecx
000000000042C4F4 83C001 add eax,$01
SteviesExample.dpr.28: end;
000000000042C4F7 83452801 add dword ptr [rbp+$28],$01
SteviesExample.dpr.24: for i := Low(values) to High(values) do
000000000042C4FB 83E801 sub eax,$01
000000000042C4FE 85C0 test eax,eax
000000000042C500 75F5 jnz TRec.&op_Implicit + $37
000000000042C502 90 nop
SteviesExample.dpr.31: end;
000000000042C503 8B452C mov eax,[rbp+$2c]
000000000042C506 488D6530 lea rsp,[rbp+$30]
000000000042C50A 5D pop rbp
000000000042C50B C3 ret
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 14. Dez 2023, 07:36
Könnte das damit zusammenhängen?
Die Stichwörter sind alle da:

https://docwiki.embarcadero.com/RADS...y_Improvements
Zitat:
The hidden "high bound" parameter type for an open array parameter was changed from Integer to NativeInt, an alias of Integer or Int64, depending on the target CPU. This means that Length, High, and Low for open array parameters in 64-bit compilers now return 64-bit value.
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.008 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#9

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 7. Feb 2024, 13:42
RSP-43656 taucht zumindest in der Liste der in Patch 1 gefixten Issues auf
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Delphi 12: Enum Value to Record per Implicit-Operator ist kaputt

  Alt 13. Feb 2024, 07:49
RSP-43656 taucht zumindest in der Liste der in Patch 1 gefixten Issues auf
Kann ich als gefixt bestätigen.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz