Переглянути джерело

Fix Mantis #21179

* defcmp.pas:
        + Extend compare_def_ext by the possiblity to specify whether strict or
          loose comparison of undefined defs should be applied.
          * in strict mode undefined defs are incompatible to all other defs
            except other undefined defs
          * in loose mode undefined defs are equal to anything (this is how
            FPC behaved up to now)
        + Enable the strict mode in compare_paras so that overloads with
          generic type parameters are possible
* ptype.pas, single_type:
        If the generic dummy of the currently parsed generic is encountered in
        non-Delphi modes then we need to return the current genericdef. This
        condition needs to be checked using the ObjName of the def, because
        the link from the type symbol to the current def is not yet 
        established 
+ added test for bug report

git-svn-id: trunk@20345 -
svenbarth 13 роки тому
батько
коміт
2a872978dc
4 змінених файлів з 72 додано та 10 видалено
  1. 1 0
      .gitattributes
  2. 42 10
      compiler/defcmp.pas
  3. 7 0
      compiler/ptype.pas
  4. 22 0
      tests/webtbs/tw21179.pp

+ 1 - 0
.gitattributes

@@ -12224,6 +12224,7 @@ tests/webtbs/tw2110.pp svneol=native#text/plain
 tests/webtbs/tw21146.pp svneol=native#text/pascal
 tests/webtbs/tw21146.pp svneol=native#text/pascal
 tests/webtbs/tw21151.pp svneol=native#text/plain
 tests/webtbs/tw21151.pp svneol=native#text/plain
 tests/webtbs/tw21177.pp svneol=native#text/plain
 tests/webtbs/tw21177.pp svneol=native#text/plain
+tests/webtbs/tw21179.pp svneol=native#text/pascal
 tests/webtbs/tw2128.pp svneol=native#text/plain
 tests/webtbs/tw2128.pp svneol=native#text/plain
 tests/webtbs/tw2129.pp svneol=native#text/plain
 tests/webtbs/tw2129.pp svneol=native#text/plain
 tests/webtbs/tw2129b.pp svneol=native#text/plain
 tests/webtbs/tw2129b.pp svneol=native#text/plain

+ 42 - 10
compiler/defcmp.pas

@@ -50,7 +50,15 @@ interface
 
 
        tcompare_paras_options = set of tcompare_paras_option;
        tcompare_paras_options = set of tcompare_paras_option;
 
 
-       tcompare_defs_option = (cdo_internal,cdo_explicit,cdo_check_operator,cdo_allow_variant,cdo_parameter,cdo_warn_incompatible_univ);
+       tcompare_defs_option = (
+          cdo_internal,
+          cdo_explicit,
+          cdo_check_operator,
+          cdo_allow_variant,
+          cdo_parameter,
+          cdo_warn_incompatible_univ,
+          cdo_strict_undefined_check  // undefined defs are incompatible to everything except other undefined defs
+       );
        tcompare_defs_options = set of tcompare_defs_option;
        tcompare_defs_options = set of tcompare_defs_option;
 
 
        tconverttype = (tc_none,
        tconverttype = (tc_none,
@@ -210,14 +218,38 @@ implementation
             exit;
             exit;
           end;
           end;
 
 
-         { undefined def? then mark it as equal }
-         if (def_from.typ=undefineddef) or
-            (def_to.typ=undefineddef) then
-          begin
-            doconv:=tc_equal;
-            compare_defs_ext:=te_exact;
-            exit;
-          end;
+         if cdo_strict_undefined_check in cdoptions then
+           begin
+             { undefined defs are considered equal if both are undefined defs }
+             if (def_from.typ=undefineddef) and
+                (def_to.typ=undefineddef) then
+              begin
+                doconv:=tc_equal;
+                compare_defs_ext:=te_exact;
+                exit;
+              end;
+
+             { if only one def is a undefined def then they are not considered as
+               equal}
+             if (def_from.typ=undefineddef) or
+                (def_to.typ=undefineddef) then
+              begin
+                doconv:=tc_not_possible;
+                compare_defs_ext:=te_incompatible;
+                exit;
+              end;
+           end
+         else
+           begin
+             { undefined defs are considered equal }
+             if (def_from.typ=undefineddef) or
+                (def_to.typ=undefineddef) then
+              begin
+                doconv:=tc_equal;
+                compare_defs_ext:=te_exact;
+                exit;
+              end;
+           end;
 
 
          { we walk the wanted (def_to) types and check then the def_from
          { we walk the wanted (def_to) types and check then the def_from
            types if there is a conversion possible }
            types if there is a conversion possible }
@@ -1668,7 +1700,7 @@ implementation
         i1,i2     : byte;
         i1,i2     : byte;
       begin
       begin
          compare_paras:=te_incompatible;
          compare_paras:=te_incompatible;
-         cdoptions:=[cdo_parameter,cdo_check_operator,cdo_allow_variant];
+         cdoptions:=[cdo_parameter,cdo_check_operator,cdo_allow_variant,cdo_strict_undefined_check];
          { we need to parse the list from left-right so the
          { we need to parse the list from left-right so the
            not-default parameters are checked first }
            not-default parameters are checked first }
          lowesteq:=high(tequaltype);
          lowesteq:=high(tequaltype);

+ 7 - 0
compiler/ptype.pas

@@ -400,6 +400,13 @@ implementation
                 Message(parser_e_no_generics_as_types);
                 Message(parser_e_no_generics_as_types);
                 def:=generrordef;
                 def:=generrordef;
               end
               end
+            else if (def.typ=undefineddef) and (sp_generic_dummy in srsym.symoptions)
+                and parse_generic and
+                (current_genericdef.typ in [recorddef,objectdef]) and
+                (Pos(upper(srsym.realname),tabstractrecorddef(current_genericdef).objname^)=1) then
+              begin
+                def:=current_genericdef;
+              end
             else if is_classhelper(def) and
             else if is_classhelper(def) and
                 not (stoParseClassParent in options) then
                 not (stoParseClassParent in options) then
               begin
               begin

+ 22 - 0
tests/webtbs/tw21179.pp

@@ -0,0 +1,22 @@
+{ %NORUN }
+
+{$mode OBJFPC}
+{$modeswitch ADVANCEDRECORDS}
+program generic_record_op_bug;
+
+type generic GVec3<T> = record
+  D : Byte;
+  class operator *( const A, B : GVec3 ) : GVec3;
+  class operator *( const A : GVec3; Scalar : T ) : GVec3;
+end;
+
+class operator GVec3.*( const A, B : GVec3 ) : GVec3;
+begin
+end;
+
+class operator GVec3.*( const A : GVec3; Scalar : T ) : GVec3;
+begin
+end;
+
+begin
+end.