Prechádzať zdrojové kódy

* Add missing methods to thunk class for parent interfaces without RTTI

Michaël Van Canneyt 8 mesiacov pred
rodič
commit
e1e301dea8
3 zmenil súbory, kde vykonal 91 pridanie a 33 odobranie
  1. 51 33
      compiler/symcreat.pas
  2. 20 0
      tests/test/tthunkpc1.pp
  3. 20 0
      tests/test/tthunkpc2.pp

+ 51 - 33
compiler/symcreat.pas

@@ -1579,7 +1579,7 @@ implementation
     pd : tprocdef;
     odef,def : tobjectdef;
     offs,argcount,i,j : integer;
-
+    intfDef : tobjectdef;
   begin
     str:='type '#10;
     odef:=getparent_interface_def(objdef);
@@ -1589,27 +1589,36 @@ implementation
       parentname:=odef.hiddenclassdef.GetTypeName;
     str:=str+cn+' = class('+parentname+','+objdef.GetTypeName+')'#10;
     str:=str+' protected '#10;
-    for I:=0 to objdef.symtable.symList.Count-1 do
-      begin
-      sym:=tsym(objdef.symtable.symList[i]);
-      if Not assigned(sym) then
-        continue;
-      if (Sym.typ<>procsym) then
-        continue;
-      for j:=0 to proc.ProcdefList.Count-1 do
-        begin
-        pd:=tprocdef(proc.ProcdefList[j]);
-        if pd.returndef<>voidtype then
-          str:=str+'function '
-        else
-          str:=str+'procedure ';
-        str:=str+proc.RealName;
-        str:=str+create_intf_method_args(pd,argcount);
-        if pd.returndef<>voidtype then
-          str:=str+' : '+get_method_paramtype(pd.returndef,false);
-        str:=str+';'#10;
-        end;
-      end;
+    Intfdef:=objdef;
+    Repeat
+      if not IntfDef.is_generic then
+        for I:=0 to intfdef.symtable.symList.Count-1 do
+          begin
+          sym:=tsym(intfdef.symtable.symList[i]);
+          if Not assigned(sym) then
+            continue;
+          if (Sym.typ<>procsym) then
+            continue;
+          for j:=0 to proc.ProcdefList.Count-1 do
+            begin
+            pd:=tprocdef(proc.ProcdefList[j]);
+            if pd.returndef<>voidtype then
+              str:=str+'function '
+            else
+              str:=str+'procedure ';
+            str:=str+proc.RealName;
+            str:=str+create_intf_method_args(pd,argcount);
+            if pd.returndef<>voidtype then
+              str:=str+' : '+get_method_paramtype(pd.returndef,false);
+            str:=str+';'#10;
+            end;
+          end;
+      // Check parent class
+      intfdef:=getparent_interface_def(intfdef);
+      // If we already have a hidden class def for it, no need to continue
+      if (IntfDef<>nil) and (IntfDef.hiddenclassdef<>nil) then
+        IntfDef:=Nil;
+    until intfdef=nil;
     offs:=get_thunkclass_interface_vmtoffset(objdef);
     if offs>0 then
       begin
@@ -1759,24 +1768,33 @@ implementation
     proc : tprocsym absolute sym;
     pd : tprocdef;
     offs,i,j : integer;
+    intfDef : tobjectdef;
 
   begin
     offs:=get_thunkclass_interface_vmtoffset(objdef);
     if offs>0 then
       implement_thunkclass_interfacevmtoffset(cn,objdef,offs);
-    for I:=0 to objdef.symtable.symList.Count-1 do
-      begin
-      sym:=tsym(objdef.symtable.symList[i]);
-      if Not assigned(sym) then
-        continue;
-      if (Sym.typ<>procsym) then
-        continue;
-      for j:=0 to proc.ProcdefList.Count-1 do
+    intfDef:=objdef;
+    repeat
+      for I:=0 to intfdef.symtable.symList.Count-1 do
         begin
-        pd:=tprocdef(proc.ProcdefList[j]);
-        implement_interface_thunkclass_impl_method(cn,objdef,proc,pd);
+        sym:=tsym(intfdef.symtable.symList[i]);
+        if Not assigned(sym) then
+          continue;
+        if (Sym.typ<>procsym) then
+          continue;
+        for j:=0 to proc.ProcdefList.Count-1 do
+          begin
+          pd:=tprocdef(proc.ProcdefList[j]);
+          implement_interface_thunkclass_impl_method(cn,intfdef,proc,pd);
+          end;
         end;
-      end;
+      // Check parent class.
+      intfdef:=getparent_interface_def(intfdef);
+      // If we already have a hidden class def for it, no need to continue
+      if (intfdef<>Nil) and (IntfDef.hiddenclassdef<>nil) then
+        IntfDef:=Nil;
+    until (intfdef=Nil);
   end;
 
   procedure add_synthetic_interface_classes_for_st(st : tsymtable; gen_intf, gen_impl : boolean);

+ 20 - 0
tests/test/tthunkpc1.pp

@@ -0,0 +1,20 @@
+{ %CPU=wasm32 }
+// Test that methods of parent interfaces (without RTTI and hence no thunk class) are also added to thunk class.
+// tthunkpc2 contains interface without rtti
+unit tthunkpc1;
+
+{$mode objfpc}
+
+interface
+
+uses tthunkpc2;
+
+Type
+  {$M+}
+  IB = Interface(IAS)
+    Procedure methodB;
+  end;
+  
+implementation
+
+end.     

+ 20 - 0
tests/test/tthunkpc2.pp

@@ -0,0 +1,20 @@
+{ %CPU=wasm32 }
+// Test that methods of parent interfaces (without RTTI and hence no thunk class) are also added to thunk class.
+// This unit contains a parent interface without RTTI (see tthunkpc1)
+unit tthunkpc2;
+
+{$mode objfpc}
+
+interface
+
+Type
+  generic IA<T> = Interface  ['{9457c0d1-4ae6-40e3-94c0-486439b30e4c}']
+    Procedure methodA(a : T);
+  end;
+  
+  IAS = Interface(specialize IA<String>) ['{9457c0d1-4ae6-40e3-94c0-486439b30e4d}'] 
+  end;
+ 
+implementation
+
+end.