Bladeren bron

* never use a linear table for enum<->string translation when two enums have
the same value (mantis #22570)

git-svn-id: trunk@22276 -

Jonas Maebe 13 jaren geleden
bovenliggende
commit
4cae00f97a
3 gewijzigde bestanden met toevoegingen van 83 en 1 verwijderingen
  1. 1 0
      .gitattributes
  2. 15 1
      compiler/ncgrtti.pas
  3. 67 0
      tests/webtbs/tw22570.pp

+ 1 - 0
.gitattributes

@@ -12805,6 +12805,7 @@ tests/webtbs/tw22490.pp svneol=native#text/plain
 tests/webtbs/tw2250.pp svneol=native#text/plain
 tests/webtbs/tw22502.pp svneol=native#text/plain
 tests/webtbs/tw22561.pp svneol=native#text/plain
+tests/webtbs/tw22570.pp svneol=native#text/plain
 tests/webtbs/tw2259.pp svneol=native#text/plain
 tests/webtbs/tw22593.pp svneol=native#text/plain
 tests/webtbs/tw2260.pp svneol=native#text/plain

+ 15 - 1
compiler/ncgrtti.pas

@@ -973,7 +973,7 @@ implementation
         procedure enumdef_rtti_ord2stringindex(const sym_count:longint; const offsets:plongint; const syms:Penumsym; const st:longint);
 
         var rttilab:Tasmsymbol;
-            h,i,o:longint;
+            h,i,o,prev_value:longint;
             mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
             r:single;             {Must be real type because of integer overflow risk.}
 
@@ -986,10 +986,24 @@ implementation
               i:=1;
               r:=0;
               h:=syms[0].value; {Next expected enum value is min.}
+              { set prev_value for the first iteration to a value that is
+                different from the first one without risking overflow (it's used
+                to detect whether two enum values are the same) }
+              if h=0 then
+                prev_value:=1
+              else
+                prev_value:=0;
               while i<sym_count do
                 begin
+                  { if two enum values are the same, we have to create a table }
+                  if (prev_value=h) then
+                    begin
+                      mode:=search;
+                      break;
+                    end;
                   {Calculate size of hole between values. Avoid integer overflows.}
                   r:=r+(single(syms[i].value)-single(h))-1;
+                  prev_value:=h;
                   h:=syms[i].value;
                   inc(i);
                 end;

+ 67 - 0
tests/webtbs/tw22570.pp

@@ -0,0 +1,67 @@
+type
+  TChomskyType = ( ctNoneGrammar = 0,
+                   ctType0 = 1, ctRecursivelyEnumerable = ctType0,
+                   ctType1 = 2, ctContextSensitive = ctType1,
+                   ctType2 = 3, ctContextFree = ctType2,
+                   ctType3 = 4, ctRegular = ctType3);
+
+var
+  e: TChomskyType;
+  err: longint;
+  s: shortstring;
+begin
+  val('ctType0',e,err);
+  if e<>ctType0 then
+    halt(1);
+
+  val('ctRecursivelyEnumerable',e,err);
+  if e<>ctRecursivelyEnumerable then
+    halt(2);
+
+  val('ctType1',e,err);
+  if e<>ctType1 then
+    halt(3);
+
+  val('ctContextSensitive',e,err);
+  if e<>ctContextSensitive then
+    halt(4);
+
+  val('ctType2',e,err);
+  if e<>ctType2 then
+    halt(5);
+
+  val('ctContextFree',e,err);
+  if e<>ctContextFree then
+    halt(6);
+
+  str(ctType0,s);
+  { could be either since they have the same value }
+  if (s<>'ctType0') and
+     (s<>'ctRecursivelyEnumerable') then
+    halt(7);
+
+  str(ctRecursivelyEnumerable,s);
+  if (s<>'ctType0') and
+     (s<>'ctRecursivelyEnumerable') then
+    halt(8);
+
+  str(ctType1,s);
+  if (s<>'ctType1') and
+     (s<>'ctContextSensitive') then
+    halt(9);
+
+  str(ctContextSensitive,s);
+  if (s<>'ctType1') and
+     (s<>'ctContextSensitive') then
+    halt(9);
+
+  str(ctType2,s);
+  if (s<>'ctType2') and
+     (s<>'ctContextFree') then
+    halt(10);
+
+  str(ctContextFree,s);
+  if (s<>'ctType2') and
+     (s<>'ctContextFree') then
+    halt(10);
+end.