Subj silently produces invalid codegen: -------8<------- var Z: procedure of object;
type R = record procedure Foo; end; procedure R.Foo; begin end; type O = object procedure Foo; end; procedure O.Foo; begin end; type C = class procedure Foo; class procedure ClassCtx; end; procedure C.Foo; begin end; class procedure C.ClassCtx; begin Z := Foo; // BadCG: .Code = C.Foo; .Data = C end; type CC = class of C; var aCC: CC = nil; type H = class helper for C procedure Bar; class procedure ClassCtx2; end; procedure H.Bar; begin end; class procedure H.ClassCtx2; begin Z := Bar; // BadCG: .Code = H.Bar; .Data = C end; begin Z := R.Foo; // BadCG: GARBAGE Z := O.Foo; // BadCG: GARBAGE Z := C.Foo; // BadCG: .Code = C.Foo; .Data = C Z := CC.Foo; // BadCG: GARBAGE Z := aCC.Foo; // BadCG: .Code = C.Foo; .Data = aCC // Currently allowed, and we get the fix for this for free. // Such qualification may become rejected; // see https://lists.freepascal.org/pipermail/fpc-devel/2021-December/044251.html Z := H.Bar; // BadCG: GARBAGE end. -------8<------- The attached methptr_to_instancemeth_via_type.patch catches all these cases and reports the proper error:
Error: Only class methods, class properties and class variables can be referred with class references
-- βþ
# HG changeset patch # User Blaise.ru # Date 1640264248 -10800 # Thu Dec 23 15:57:28 2021 +0300 ! reject assignments of instance methods, accessed via a type, to method pointers (invalid codegen) diff -r d880e6695537 -r 4fddd039bb22 pexpr.pas --- a/pexpr.pas Mon Dec 20 20:55:22 2021 +0300 +++ b/pexpr.pas Thu Dec 23 15:57:28 2021 +0300 @@ -1361,8 +1361,26 @@ again,p1,callflags,spezcontext); { we need to know which procedure is called } do_typecheckpass(p1); + + { We are loading... } + if p1.nodetype=loadn then + begin + if + { an instance method } + not(po_classmethod in tloadnode(p1).procdef.procoptions) + { into a method pointer (not just taking a code address) } + and not getaddr + { and the selfarg is... } + and( + { either a record/object/helper type, } + not assigned(tloadnode(p1).left) + { or a class/metaclass type, or a class reference } + or{else} (tloadnode(p1).left.resultdef.typ=classrefdef) + ) then + Message(parser_e_only_class_members_via_class_ref); + end { calling using classref? } - if ( + else if ( isclassref or ( (isobjecttype or
_______________________________________________ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel