* 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 -
This commit is contained in:
svenbarth 2012-02-13 21:17:54 +00:00
parent 429af6f40b
commit 2a872978dc
4 changed files with 72 additions and 10 deletions

1
.gitattributes vendored
View File

@ -12224,6 +12224,7 @@ tests/webtbs/tw2110.pp svneol=native#text/plain
tests/webtbs/tw21146.pp svneol=native#text/pascal
tests/webtbs/tw21151.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/tw2129.pp svneol=native#text/plain
tests/webtbs/tw2129b.pp svneol=native#text/plain

View File

@ -50,7 +50,15 @@ interface
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;
tconverttype = (tc_none,
@ -210,14 +218,38 @@ implementation
exit;
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
types if there is a conversion possible }
@ -1668,7 +1700,7 @@ implementation
i1,i2 : byte;
begin
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
not-default parameters are checked first }
lowesteq:=high(tequaltype);

View File

@ -400,6 +400,13 @@ implementation
Message(parser_e_no_generics_as_types);
def:=generrordef;
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
not (stoParseClassParent in options) then
begin

22
tests/webtbs/tw21179.pp Normal file
View File

@ -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.