[fpc-devel] Assigning instance methods, accessed via a type, to method pointers
Blaise at blaise.ru
Blaise at blaise.ru
Thu Dec 23 19:13:01 CET 2021
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
--
βþ
-------------- next part --------------
# 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
More information about the fpc-devel
mailing list