From 485d6b4445c7c87b9a831b8fbd2df2d515358e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D0=BD=D0=B4=D0=B0=D1=80=D0=B5=D0=B2=20=D0=98?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD?= Date: Thu, 6 Jul 2017 20:33:38 +0200 Subject: [PATCH] bug fix #428 --- NETGenerator/NETGenerator.cs | 56 ++++++++++++++++++++++++------------ Optimizer/Optimizer.cs | 2 +- TestSuite/boxing1.pas | 9 ++++++ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/NETGenerator/NETGenerator.cs b/NETGenerator/NETGenerator.cs index 26c3cc6f5..a5e635c95 100644 --- a/NETGenerator/NETGenerator.cs +++ b/NETGenerator/NETGenerator.cs @@ -5085,7 +5085,7 @@ namespace PascalABCCompiler.NETGenerator public override void visit(SemanticTree.IStaticCompiledFieldReferenceNode value) { //если у поля нет постоянное значение - if (value.static_field.compiled_field.IsLiteral == false) + if (!value.static_field.compiled_field.IsLiteral) { if (is_addr == false) { @@ -5102,7 +5102,7 @@ namespace PascalABCCompiler.NETGenerator { //иначе кладем константу NETGeneratorTools.PushLdc(il, value.static_field.compiled_field.FieldType, value.static_field.compiled_field.GetRawConstantValue()); - if (is_dot_expr == true) + if (is_dot_expr) { //нужно упаковать il.Emit(OpCodes.Box, value.static_field.compiled_field.FieldType); @@ -5132,7 +5132,7 @@ namespace PascalABCCompiler.NETGenerator else { NETGeneratorTools.PushLdc(il, value.field.compiled_field.FieldType, value.field.compiled_field.GetRawConstantValue()); - if (tmp_dot == true) + if (tmp_dot) { il.Emit(OpCodes.Box, value.field.compiled_field.FieldType); } @@ -5164,13 +5164,6 @@ namespace PascalABCCompiler.NETGenerator } else il.Emit(OpCodes.Ldsflda, fi); - /*if (is_dot_expr) - { - //здесь в условии ошибка - //(ssyy) интересно, какая:) Добавил проверку для generics - if (fi.FieldType.IsValueType && fi.FieldType.IsPrimitive || fi.FieldType.IsGenericParameter) - il.Emit(OpCodes.Box, fi.FieldType); - }*/ } public override void visit(SemanticTree.ICommonClassFieldReferenceNode value) @@ -5247,9 +5240,9 @@ namespace PascalABCCompiler.NETGenerator if (vi.kind == VarKind.vkLocal)//если локальная { LocalBuilder lb = vi.lb; - if (is_addr == false)//если это факт. var-параметр + if (!is_addr)//если это факт. var-параметр { - if (is_dot_expr == true) //если после перем. в выражении стоит точка + if (is_dot_expr) //если после перем. в выражении стоит точка { if (lb.LocalType.IsGenericParameter) { @@ -5257,7 +5250,7 @@ namespace PascalABCCompiler.NETGenerator il.Emit(OpCodes.Box, lb.LocalType); } else - if (lb.LocalType.IsValueType == true) + if (lb.LocalType.IsValueType) { il.Emit(OpCodes.Ldloca, lb);//если перем. размерного типа кладем ее адрес } @@ -6635,8 +6628,11 @@ namespace PascalABCCompiler.NETGenerator //ICompiledTypeNode ctn = value.real_parameters[i].type as ICompiledTypeNode; ICompiledTypeNode ctn2 = parameters[i].type as ICompiledTypeNode; ITypeNode ctn3 = real_parameters[i].type; + ITypeNode ctn4 = real_parameters[i].conversion_type; if (ctn2 != null && !(real_parameters[i] is SemanticTree.INullConstantNode) && (ctn3.is_value_type || ctn3.is_generic_parameter) && ctn2.compiled_type == TypeFactory.ObjectType) il.Emit(OpCodes.Box, helper.GetTypeReference(ctn3).tp); + else if (ctn2 != null && !(real_parameters[i] is SemanticTree.INullConstantNode) && ctn4 != null && (ctn4.is_value_type || ctn4.is_generic_parameter) && ctn2.compiled_type == TypeFactory.ObjectType) + il.Emit(OpCodes.Box, helper.GetTypeReference(ctn4).tp); is_addr = false; } //вызов метода @@ -6692,10 +6688,12 @@ namespace PascalABCCompiler.NETGenerator is_dot_expr = true; //DarkStar Fixed: type t:=i.gettype(); bool _box = value.obj.type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType; + if (!_box && value.obj.conversion_type != null) + _box = value.obj.conversion_type != null && value.obj.conversion_type.is_value_type; if (_box) is_dot_expr = false; value.obj.visit(this); - if ((value.obj.type.is_value_type) && !value.compiled_method.method_info.DeclaringType.IsValueType) + if (value.obj.type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType) { il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.type).tp); } @@ -6705,6 +6703,10 @@ namespace PascalABCCompiler.NETGenerator il.Emit(OpCodes.Stloc, lb); il.Emit(OpCodes.Ldloca, lb); } + else if (value.obj.conversion_type != null && value.obj.conversion_type.is_value_type && !value.compiled_method.method_info.DeclaringType.IsValueType) + { + il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.conversion_type).tp); + } is_dot_expr = false; EmitArguments(parameters, real_parameters); /*for (int i = 0; i < real_parameters.Length; i++) @@ -6847,7 +6849,7 @@ namespace PascalABCCompiler.NETGenerator MethodInfo mi = meth.mi; IExpressionNode[] real_parameters = value.real_parameters; bool tmp_dot = is_dot_expr; - if (tmp_dot == false) + if (!tmp_dot) is_dot_expr = true; value.obj.visit(this); if ((value.obj.type.is_value_type) && !value.method.common_comprehensive_type.is_value_type) @@ -6860,6 +6862,10 @@ namespace PascalABCCompiler.NETGenerator il.Emit(OpCodes.Stloc, lb); il.Emit(OpCodes.Ldloca, lb); } + else if (value.obj.conversion_type != null && value.obj.conversion_type.is_value_type && !value.method.common_comprehensive_type.is_value_type) + { + il.Emit(OpCodes.Box, helper.GetTypeReference(value.obj.conversion_type).tp); + } is_dot_expr = false; //bool is_comp_gen = false; //bool need_fee = false; @@ -6939,9 +6945,7 @@ namespace PascalABCCompiler.NETGenerator { TypeInfo ti = helper.GetTypeReference(parameter.type); if (ti != null && ti.clone_meth != null && parameter.parameter_type == parameter_type.value && !parameter.is_const && - parameter.type.type_special_kind != type_special_kind.base_set_type /*&& - !(expr is ICompiledConstructorCall) && - !(expr is ICommonConstructorCall)*/) + parameter.type.type_special_kind != type_special_kind.base_set_type) { il.Emit(OpCodes.Call, ti.clone_meth); return true; @@ -7539,6 +7543,10 @@ namespace PascalABCCompiler.NETGenerator { il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp); } + else if (from.conversion_type != null && (from.type.is_value_type || from.type.is_generic_parameter) && ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType) + { + il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp); + } CheckArrayAssign(to, from, il); } @@ -7925,6 +7933,10 @@ namespace PascalABCCompiler.NETGenerator { il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp); } + else if (from.conversion_type != null && (from.conversion_type.is_value_type || from.conversion_type.is_generic_parameter) && ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType) + { + il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp); + } CheckArrayAssign(to, from, il); if (value.indices == null) @@ -7958,6 +7970,10 @@ namespace PascalABCCompiler.NETGenerator { il.Emit(OpCodes.Box, helper.GetTypeReference(from.type).tp); } + else if (from.conversion_type != null && (from.conversion_type.is_value_type || from.conversion_type.is_generic_parameter) && ctn2 != null && ctn2.compiled_type == TypeFactory.ObjectType) + { + il.Emit(OpCodes.Box, helper.GetTypeReference(from.conversion_type).tp); + } CheckArrayAssign(to, from, il); NETGeneratorTools.PushStind(il, ti.tp); if (TypeNeedToFix(value.type)) @@ -9185,6 +9201,8 @@ namespace PascalABCCompiler.NETGenerator cmcall.obj.visit(this); if (cmcall.obj.type.is_value_type) il.Emit(OpCodes.Box, helper.GetTypeReference(cmcall.obj.type).tp); + else if (cmcall.obj.conversion_type != null && cmcall.obj.conversion_type.is_value_type) + il.Emit(OpCodes.Box, helper.GetTypeReference(cmcall.obj.conversion_type).tp); return; } SemanticTree.ICommonStaticMethodCallNode csmcall = ifc as SemanticTree.ICommonStaticMethodCallNode; @@ -9199,6 +9217,8 @@ namespace PascalABCCompiler.NETGenerator cmccall.obj.visit(this); if (cmccall.obj.type.is_value_type) il.Emit(OpCodes.Box, helper.GetTypeReference(cmccall.obj.type).tp); + else if (cmccall.obj.conversion_type != null && cmccall.obj.conversion_type.is_value_type) + il.Emit(OpCodes.Box, helper.GetTypeReference(cmccall.obj.conversion_type).tp); return; } SemanticTree.ICompiledStaticMethodCallNode csmcall2 = ifc as SemanticTree.ICompiledStaticMethodCallNode; diff --git a/Optimizer/Optimizer.cs b/Optimizer/Optimizer.cs index 19edbd949..f89b9cba2 100644 --- a/Optimizer/Optimizer.cs +++ b/Optimizer/Optimizer.cs @@ -384,7 +384,7 @@ namespace PascalABCCompiler private void VisitStatement(statement_node sn) { if (sn == null) return; - if (!(sn is statements_list) && is_break_stmt && !has_goto) + if (!(sn is statements_list) && is_break_stmt && !has_goto && !(sn is empty_statement)) { warns.Add(new UnreachableCodeDetected(sn.location)); is_break_stmt = false; diff --git a/TestSuite/boxing1.pas b/TestSuite/boxing1.pas index 3e4c82233..ff40a31af 100644 --- a/TestSuite/boxing1.pas +++ b/TestSuite/boxing1.pas @@ -1,10 +1,19 @@ +procedure test2(params arr: array of object); +begin + assert(integer(arr[0]) = 123); +end; + procedure test(o: object); begin assert(integer(o) = 123); end; + begin var i := 123; var j := object(i); assert(integer(j) = 123); test(object(i)); + test2(object(i),2); + writeln(object(i).ToString); + assert(object(i).ToString = '123'); end. \ No newline at end of file