2
0
Эх сурвалжийг харах

compiler: compare enumerator operator "current" return type with the loop variable while searching for enumerator

git-svn-id: trunk@15953 -
paul 15 жил өмнө
parent
commit
4718c88f8d

+ 1 - 1
compiler/nflw.pas

@@ -858,7 +858,7 @@ implementation
             else
               begin
                 // 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 (pd=nil) and (expr.resultdef.typ=objectdef) then
                   pd:=tobjectdef(expr.resultdef).search_enumerator_get;

+ 55 - 38
compiler/symsym.pas

@@ -105,7 +105,7 @@ interface
           function find_procdef_byoptions(ops:tprocoptions): Tprocdef;
           function find_procdef_byprocvardef(d:Tprocvardef):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;
        end;
 
@@ -729,8 +729,7 @@ implementation
         eq      : tequaltype;
       begin
         { 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;
         bestpd:=nil;
         besteq:=te_incompatible;
@@ -792,19 +791,19 @@ implementation
         result:=bestpd;
       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
         paraidx, realparamcount,
         i, j : longint;
         bestpd,
         hpd,
         pd : tprocdef;
+        current : tpropertysym;
         convtyp : tconverttype;
         eq      : tequaltype;
       begin
         { 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;
         bestpd:=nil;
         besteq:=te_incompatible;
@@ -813,41 +812,59 @@ implementation
             pd:=tprocdef(ProcdefList[i]);
             if (pd.owner.symtabletype=staticsymtable) and not pd.owner.iscurrentunit then
               continue;
-            paraidx:=0;
-            { ignore vs_hidden parameters }
-            while (paraidx<pd.paras.count) and
-                  assigned(pd.paras[paraidx]) and
-                  (vo_is_hidden_para in tparavarsym(pd.paras[paraidx]).varoptions) do
-              inc(paraidx);
-            realparamcount:=0;
-            for j := 0 to pd.paras.Count-1 do
-              if assigned(pd.paras[j]) and not (vo_is_hidden_para in tparavarsym(pd.paras[j]).varoptions) then
-                inc(realparamcount);
-            if (paraidx<pd.paras.count) and
-               assigned(pd.paras[paraidx]) and
-               (realparamcount = 1) and
-               is_class_or_interface_or_object(pd.returndef)  then
+            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
-                eq:=compare_defs_ext(typedef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
+                paraidx:=0;
+                { ignore vs_hidden parameters }
+                while (paraidx<pd.paras.count) and
+                      assigned(pd.paras[paraidx]) and
+                      (vo_is_hidden_para in tparavarsym(pd.paras[paraidx]).varoptions) do
+                  inc(paraidx);
+                realparamcount:=0;
+                for j := 0 to pd.paras.Count-1 do
+                  if assigned(pd.paras[j]) and not (vo_is_hidden_para in tparavarsym(pd.paras[j]).varoptions) then
+                    inc(realparamcount);
+                if (paraidx<pd.paras.count) and
+                   assigned(pd.paras[paraidx]) and
+                   (realparamcount = 1) then
+                  begin
+                    eq:=compare_defs_ext(fromdef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
 
-                { alias? if yes, only l1 choice,
-                  if you mess with this code, check tw4093 }
-                if (eq=te_exact) and
-                   (typedef<>tparavarsym(pd.paras[paraidx]).vardef) and
-                   ((df_unique in typedef.defoptions) or
-                   (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
-                  eq:=te_convert_l1;
+                    { alias? if yes, only l1 choice,
+                      if you mess with this code, check tw4093 }
+                    if (eq=te_exact) and
+                       (fromdef<>tparavarsym(pd.paras[paraidx]).vardef) and
+                       ((df_unique in fromdef.defoptions) or
+                       (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
+                      eq:=te_convert_l1;
 
-                if eq=te_exact then
-                  begin
-                    besteq:=eq;
-                    result:=pd;
-                    exit;
-                  end;
-                if eq>besteq then
-                  begin
-                    bestpd:=pd;
-                    besteq:=eq;
+                    if eq=te_exact then
+                      begin
+                        besteq:=eq;
+                        result:=pd;
+                        exit;
+                      end;
+                    if eq>besteq then
+                      begin
+                        bestpd:=pd;
+                        besteq:=eq;
+                      end;
                   end;
               end;
           end;

+ 3 - 3
compiler/symtable.pas

@@ -211,7 +211,7 @@ interface
     function  search_named_unit_globaltype(const unitname, typename: TIDString; throwerror: boolean): ttypesym;
     function  search_class_member(pd : tobjectdef;const s : string):tsym;
     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;
     function  search_class_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
     function  search_objc_method(const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
     {Looks for macro s (must be given in upper case) in the macrosymbolstack, }
@@ -2181,7 +2181,7 @@ implementation
       end;
 
 
-    function search_enumerator_operator(type_def:Tdef): Tprocdef;
+    function search_enumerator_operator(from_def,to_def:Tdef): Tprocdef;
       var
         sym : Tprocsym;
         hashedid : THashedIDString;
@@ -2204,7 +2204,7 @@ implementation
                   internalerror(200910241);
                 { if the source type is an alias then this is only the second choice,
                   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
                   begin
                     besteq:=curreq;