From 6e397d17628f2122b30d50956f5f2d45175781b5 Mon Sep 17 00:00:00 2001 From: Ivan Bondarev Date: Wed, 27 Jan 2021 20:48:22 +0100 Subject: [PATCH] #2418 --- NETGenerator/NETGenerator.cs | 15 +++++++++++++-- TestSuite/generics49.pas | 21 +++++++++++++++++++++ TestSuite/generics50.pas | 20 ++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 TestSuite/generics49.pas create mode 100644 TestSuite/generics50.pas diff --git a/NETGenerator/NETGenerator.cs b/NETGenerator/NETGenerator.cs index 27820a51c..552c0a9b2 100644 --- a/NETGenerator/NETGenerator.cs +++ b/NETGenerator/NETGenerator.cs @@ -5386,6 +5386,12 @@ namespace PascalABCCompiler.NETGenerator { if (!(value.type.is_generic_parameter && value.type.base_type != null && value.type.base_type.is_class && value.type.base_type.base_type != null)) must_push_addr = true; + else if (value.type.is_generic_parameter && virtual_method_call) + { + must_push_addr = true; + virtual_method_call = false; + } + } else if (value.conversion_type != null && (value.conversion_type.is_generic_parameter)) { @@ -5560,7 +5566,7 @@ namespace PascalABCCompiler.NETGenerator //is_dot_expr = false; is_field_reference = true; value.obj.visit(this); - + is_field_reference = false; is_addr = temp_is_addr; FldInfo fi_info = helper.GetField(value.field); #if DEBUG @@ -5595,7 +5601,7 @@ namespace PascalABCCompiler.NETGenerator { is_dot_expr = false; } - is_field_reference = false; + } public override void visit(SemanticTree.INamespaceVariableReferenceNode value) @@ -7299,6 +7305,8 @@ namespace PascalABCCompiler.NETGenerator return false; } + bool virtual_method_call = false; + //вызов нестатического метода public override void visit(SemanticTree.ICommonMethodCallNode value) { @@ -7308,7 +7316,10 @@ namespace PascalABCCompiler.NETGenerator bool tmp_dot = is_dot_expr; if (!tmp_dot) is_dot_expr = true; + if ((value.method.polymorphic_state == polymorphic_state.ps_virtual || value.method.polymorphic_state == polymorphic_state.ps_virtual_abstract) && (value.obj is ICommonParameterReferenceNode || value.obj is ICommonClassFieldReferenceNode)) + virtual_method_call = true; value.obj.visit(this); + virtual_method_call = false; if ((value.obj.type.is_value_type) && !value.method.comperehensive_type.is_value_type) { if (!(value.obj is ICommonParameterReferenceNode && must_push_addr)) diff --git a/TestSuite/generics49.pas b/TestSuite/generics49.pas new file mode 100644 index 000000000..eb4f27365 --- /dev/null +++ b/TestSuite/generics49.pas @@ -0,0 +1,21 @@ +var i: integer; +type + t0 = class + // Обязательно virtual + procedure p1; virtual; + begin + i := 1; + end; + end; + +procedure p1(o: T); +where T: t0, constructor; +begin + o.p1; + var p := procedure -> o := o; +end; + +begin + p1(new t0); + assert(i = 1); +end. \ No newline at end of file diff --git a/TestSuite/generics50.pas b/TestSuite/generics50.pas new file mode 100644 index 000000000..bc5cf274c --- /dev/null +++ b/TestSuite/generics50.pas @@ -0,0 +1,20 @@ +var i: integer; +type + t0 = class + // Обязательно virtual + procedure p1; virtual; + begin + i := 1; + end; + end; + +procedure p1(o: T); +where T: t0, constructor; +begin + o.p1; +end; + +begin + p1(new t0); + assert(i = 1); +end. \ No newline at end of file