diff --git a/.gitattributes b/.gitattributes index 37e5d10909..114400011d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/compiler/defcmp.pas b/compiler/defcmp.pas index 2922c7af3f..ec7f36f6e3 100644 --- a/compiler/defcmp.pas +++ b/compiler/defcmp.pas @@ -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); diff --git a/compiler/ptype.pas b/compiler/ptype.pas index 038ce2f7f4..f3ae1f0be1 100644 --- a/compiler/ptype.pas +++ b/compiler/ptype.pas @@ -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 diff --git a/tests/webtbs/tw21179.pp b/tests/webtbs/tw21179.pp new file mode 100644 index 0000000000..0b858a5eb8 --- /dev/null +++ b/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.