Browse Source

Merge r15953-r15954:
compiler: compare enumerator operator "current" return type with the loop variable while searching for enumerator
tests: add new for-in test from Michael Van Canneyt

git-svn-id: branches/fixes_2_4@16261 -

paul 14 years ago
parent
commit
6bd7c3708c
5 changed files with 105 additions and 15 deletions
  1. 1 0
      .gitattributes
  2. 1 1
      compiler/nflw.pas
  3. 28 11
      compiler/symsym.pas
  4. 3 3
      compiler/symtable.pas
  5. 72 0
      tests/test/tforin24.pp

+ 1 - 0
.gitattributes

@@ -8326,6 +8326,7 @@ tests/test/tforin20.pp svneol=native#text/pascal
 tests/test/tforin21.pp svneol=native#text/pascal
 tests/test/tforin21.pp svneol=native#text/pascal
 tests/test/tforin22.pp svneol=native#text/pascal
 tests/test/tforin22.pp svneol=native#text/pascal
 tests/test/tforin23.pp svneol=native#text/pascal
 tests/test/tforin23.pp svneol=native#text/pascal
+tests/test/tforin24.pp svneol=native#text/pascal
 tests/test/tforin3.pp svneol=native#text/pascal
 tests/test/tforin3.pp svneol=native#text/pascal
 tests/test/tforin4.pp svneol=native#text/pascal
 tests/test/tforin4.pp svneol=native#text/pascal
 tests/test/tforin5.pp svneol=native#text/pascal
 tests/test/tforin5.pp svneol=native#text/pascal

+ 1 - 1
compiler/nflw.pas

@@ -614,7 +614,7 @@ begin
   begin
   begin
     { loop is made for an expression }
     { loop is made for an expression }
     // search for operator first
     // search for operator first
-    pd:=search_enumerator_operator(expr.resultdef);
+    pd:=search_enumerator_operator(expr.resultdef, hloopvar.resultdef);
     // if there is no operator then search for class/object enumerator method
     // if there is no operator then search for class/object enumerator method
     if (pd=nil) and (expr.resultdef.typ=objectdef) then
     if (pd=nil) and (expr.resultdef.typ=objectdef) then
       pd:=tobjectdef(expr.resultdef).search_enumerator_get;
       pd:=tobjectdef(expr.resultdef).search_enumerator_get;

+ 28 - 11
compiler/symsym.pas

@@ -102,7 +102,7 @@ interface
           function find_procdef_byoptions(ops:tprocoptions): Tprocdef;
           function find_procdef_byoptions(ops:tprocoptions): Tprocdef;
           function find_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
           function find_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
           function find_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
           function find_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
-          function find_procdef_enumerator_operator(typedef:tdef;var besteq:tequaltype):Tprocdef;
+          function find_procdef_enumerator_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
           property ProcdefList:TFPObjectList read FProcdefList;
           property ProcdefList:TFPObjectList read FProcdefList;
        end;
        end;
 
 
@@ -721,8 +721,7 @@ implementation
         eq      : tequaltype;
         eq      : tequaltype;
       begin
       begin
         { This function will return the pprocdef of pprocsym that
         { This function will return the pprocdef of pprocsym that
-          is the best match for procvardef. When there are multiple
-          matches it returns nil.}
+          is the best match for fromdef and todef. }
         result:=nil;
         result:=nil;
         bestpd:=nil;
         bestpd:=nil;
         besteq:=te_incompatible;
         besteq:=te_incompatible;
@@ -782,25 +781,43 @@ implementation
         result:=bestpd;
         result:=bestpd;
       end;
       end;
 
 
-      function Tprocsym.find_procdef_enumerator_operator(typedef:tdef;var besteq:tequaltype):Tprocdef;
+      function Tprocsym.find_procdef_enumerator_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
       var
       var
         paraidx, realparamcount,
         paraidx, realparamcount,
         i, j : longint;
         i, j : longint;
         bestpd,
         bestpd,
         hpd,
         hpd,
         pd : tprocdef;
         pd : tprocdef;
+        current : tpropertysym;
         convtyp : tconverttype;
         convtyp : tconverttype;
         eq      : tequaltype;
         eq      : tequaltype;
       begin
       begin
         { This function will return the pprocdef of pprocsym that
         { This function will return the pprocdef of pprocsym that
-          is the best match for procvardef. When there are multiple
-          matches it returns nil.}
+          is the best match for fromdef and todef. }
         result:=nil;
         result:=nil;
         bestpd:=nil;
         bestpd:=nil;
         besteq:=te_incompatible;
         besteq:=te_incompatible;
         for i:=0 to ProcdefList.Count-1 do
         for i:=0 to ProcdefList.Count-1 do
           begin
           begin
             pd:=tprocdef(ProcdefList[i]);
             pd:=tprocdef(ProcdefList[i]);
+            if not is_class_or_interface_or_object(pd.returndef) then
+              continue;
+            current := tpropertysym(tobjectdef(pd.returndef).search_enumerator_current);
+            if (current = nil) then
+              continue;
+            // compare current result def with the todef
+            if (equal_defs(todef, current.propdef) or
+                { shortstrings of different lengths are ok as result }
+                (is_shortstring(todef) and is_shortstring(current.propdef))) and
+               { the result type must be always really equal and not an alias,
+                 if you mess with this code, check tw4093 }
+               ((todef=current.propdef) or
+                (
+                  not(df_unique in todef.defoptions) and
+                  not(df_unique in current.propdef.defoptions)
+                )
+               ) then
+              begin
             paraidx:=0;
             paraidx:=0;
             { ignore vs_hidden parameters }
             { ignore vs_hidden parameters }
             while (paraidx<pd.paras.count) and
             while (paraidx<pd.paras.count) and
@@ -813,16 +830,15 @@ implementation
                 inc(realparamcount);
                 inc(realparamcount);
             if (paraidx<pd.paras.count) and
             if (paraidx<pd.paras.count) and
                assigned(pd.paras[paraidx]) and
                assigned(pd.paras[paraidx]) and
-               (realparamcount = 1) and
-               is_class_or_interface_or_object(pd.returndef)  then
+                   (realparamcount = 1) then
               begin
               begin
-                eq:=compare_defs_ext(typedef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
+                    eq:=compare_defs_ext(fromdef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
 
 
                 { alias? if yes, only l1 choice,
                 { alias? if yes, only l1 choice,
                   if you mess with this code, check tw4093 }
                   if you mess with this code, check tw4093 }
                 if (eq=te_exact) and
                 if (eq=te_exact) and
-                   (typedef<>tparavarsym(pd.paras[paraidx]).vardef) and
-                   ((df_unique in typedef.defoptions) or
+                       (fromdef<>tparavarsym(pd.paras[paraidx]).vardef) and
+                       ((df_unique in fromdef.defoptions) or
                    (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
                    (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
                   eq:=te_convert_l1;
                   eq:=te_convert_l1;
 
 
@@ -839,6 +855,7 @@ implementation
                   end;
                   end;
               end;
               end;
           end;
           end;
+          end;
         result:=bestpd;
         result:=bestpd;
       end;
       end;
 
 

+ 3 - 3
compiler/symtable.pas

@@ -201,7 +201,7 @@ interface
     function  search_system_type(const s: TIDString): ttypesym;
     function  search_system_type(const s: TIDString): ttypesym;
     function  search_class_member(pd : tobjectdef;const s : string):tsym;
     function  search_class_member(pd : tobjectdef;const s : string):tsym;
     function  search_assignment_operator(from_def,to_def:Tdef):Tprocdef;
     function  search_assignment_operator(from_def,to_def:Tdef):Tprocdef;
-    function  search_enumerator_operator(type_def:Tdef):Tprocdef;
+    function  search_enumerator_operator(from_def,to_def:Tdef):Tprocdef;
     {Looks for macro s (must be given in upper case) in the macrosymbolstack, }
     {Looks for macro s (must be given in upper case) in the macrosymbolstack, }
     {and returns it if found. Returns nil otherwise.}
     {and returns it if found. Returns nil otherwise.}
     function  search_macro(const s : string):tsym;
     function  search_macro(const s : string):tsym;
@@ -1916,7 +1916,7 @@ implementation
       end;
       end;
 
 
 
 
-    function search_enumerator_operator(type_def:Tdef): Tprocdef;
+    function search_enumerator_operator(from_def,to_def:Tdef): Tprocdef;
       var
       var
         sym : Tprocsym;
         sym : Tprocsym;
         hashedid : THashedIDString;
         hashedid : THashedIDString;
@@ -1939,7 +1939,7 @@ implementation
                   internalerror(200910241);
                   internalerror(200910241);
                 { if the source type is an alias then this is only the second choice,
                 { if the source type is an alias then this is only the second choice,
                   if you mess with this code, check tw4093 }
                   if you mess with this code, check tw4093 }
-                currpd:=sym.find_procdef_enumerator_operator(type_def,curreq);
+                currpd:=sym.find_procdef_enumerator_operator(from_def,to_def,curreq);
                 if curreq>besteq then
                 if curreq>besteq then
                   begin
                   begin
                     besteq:=curreq;
                     besteq:=curreq;

+ 72 - 0
tests/test/tforin24.pp

@@ -0,0 +1,72 @@
+program tforin24;
+
+{$mode objfpc}
+{$apptype console}
+
+uses classes;
+
+Type
+   TDayObject = Class
+     DayOfWeek : Integer;
+     Constructor Create(ADayOfWeek : Integer);
+   end;
+
+   TObjectEnumerator = Class
+     FList : TStrings;
+     FIndex : Integer;
+     Function GetCurrent : TDayObject;
+     Function MoveNext: boolean;
+     Property Current : TDayObject Read GetCurrent;
+   end;
+
+Constructor TDayObject.Create(ADayOfWeek : Integer);
+
+begin
+   DayOfWeek:=ADayOfWeek;
+end;
+
+
+Function TObjectEnumerator.GetCurrent : TDayObject;
+begin
+   Result:=FList.Objects[Findex] as TDayObject;
+end;
+
+Function TObjectEnumerator.MoveNext: boolean;
+
+begin
+   Inc(FIndex);
+   Result:=(FIndex<FList.Count);
+end;
+
+
+operator enumerator (s : TStrings) : TObjectEnumerator;
+
+begin
+   Result:=TObjectEnumerator.Create;
+   Result.Flist:=S;
+   Result.FIndex:=-1;
+end;
+
+Var
+   Days : TStrings;
+   D : String;
+   O : TdayObject;
+
+begin
+   Days:=TStringList.Create;
+   try
+     Days.AddObject('Monday',TDayObject.Create(1));
+     Days.AddObject('Tuesday',TDayObject.Create(2));
+     Days.AddObject('Wednesday',TDayObject.Create(3));
+     Days.AddObject('Thursday',TDayObject.Create(4));
+     Days.AddObject('Friday',TDayObject.Create(5));
+     Days.AddObject('Saturday',TDayObject.Create(6));
+     Days.AddObject('Sunday',TDayObject.Create(7));
+     For O in Days do
+       Writeln(O.DayOfWeek);
+     For D in Days do
+        Writeln(D);
+   Finally
+     Days.Free;
+   end;
+end.