This commit is contained in:
Ivan Bondarev 2021-08-29 10:37:11 +02:00
parent ecf7ef3663
commit f04a1c2161
2 changed files with 94 additions and 30 deletions

View file

@ -8951,8 +8951,15 @@ namespace PascalABCCompiler.NETGenerator
if (real_parameters[0].type.is_nullable_type && real_parameters[1] is INullConstantNode) if (real_parameters[0].type.is_nullable_type && real_parameters[1] is INullConstantNode)
{ {
bool tmp = is_dot_expr; bool tmp = is_dot_expr;
if (real_parameters[0] is IDefaultOperatorNode)
{
il.Emit(OpCodes.Ldc_I4_0);
}
else
{
is_dot_expr = true; is_dot_expr = true;
TypeInfo ti = helper.GetTypeReference(real_parameters[0].type); TypeInfo ti = helper.GetTypeReference(real_parameters[0].type);
real_parameters[0].visit(this); real_parameters[0].visit(this);
is_dot_expr = tmp; is_dot_expr = tmp;
MethodInfo mi = null; MethodInfo mi = null;
@ -8961,6 +8968,8 @@ namespace PascalABCCompiler.NETGenerator
else else
mi = ti.tp.GetMethod("get_HasValue"); mi = ti.tp.GetMethod("get_HasValue");
il.Emit(OpCodes.Call, mi); il.Emit(OpCodes.Call, mi);
}
if (ft == basic_function_type.objeq) if (ft == basic_function_type.objeq)
{ {
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
@ -8972,6 +8981,12 @@ namespace PascalABCCompiler.NETGenerator
else if (real_parameters[1].type.is_nullable_type && real_parameters[0] is INullConstantNode) else if (real_parameters[1].type.is_nullable_type && real_parameters[0] is INullConstantNode)
{ {
bool tmp = is_dot_expr; bool tmp = is_dot_expr;
if (real_parameters[1] is IDefaultOperatorNode)
{
il.Emit(OpCodes.Ldc_I4_0);
}
else
{
is_dot_expr = true; is_dot_expr = true;
TypeInfo ti = helper.GetTypeReference(real_parameters[1].type); TypeInfo ti = helper.GetTypeReference(real_parameters[1].type);
real_parameters[1].visit(this); real_parameters[1].visit(this);
@ -8982,6 +8997,7 @@ namespace PascalABCCompiler.NETGenerator
else else
mi = ti.tp.GetMethod("get_HasValue"); mi = ti.tp.GetMethod("get_HasValue");
il.Emit(OpCodes.Call, mi); il.Emit(OpCodes.Call, mi);
}
if (ft == basic_function_type.objeq) if (ft == basic_function_type.objeq)
{ {
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
@ -8993,22 +9009,61 @@ namespace PascalABCCompiler.NETGenerator
{ {
MethodInfo mi_left = null; MethodInfo mi_left = null;
TypeInfo ti_left = helper.GetTypeReference(real_parameters[0].type); TypeInfo ti_left = helper.GetTypeReference(real_parameters[0].type);
if (real_parameters[0] is IDefaultOperatorNode)
il.Emit(OpCodes.Ldc_I4_0);
else
{
if (real_parameters[1] is IDefaultOperatorNode)
{
if (real_parameters[0].type is IGenericTypeInstance)
mi_left = TypeBuilder.GetMethod(ti_left.tp, typeof(Nullable<>).GetMethod("get_HasValue", new Type[] { }));
else
mi_left = ti_left.tp.GetMethod("get_HasValue", new Type[] { });
}
else
{
if (real_parameters[0].type is IGenericTypeInstance) if (real_parameters[0].type is IGenericTypeInstance)
mi_left = TypeBuilder.GetMethod(ti_left.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { })); mi_left = TypeBuilder.GetMethod(ti_left.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { }));
else else
mi_left = ti_left.tp.GetMethod("GetValueOrDefault", new Type[] { }); mi_left = ti_left.tp.GetMethod("GetValueOrDefault", new Type[] { });
}
}
MethodInfo mi_right = null; MethodInfo mi_right = null;
TypeInfo ti_right = helper.GetTypeReference(real_parameters[1].type); TypeInfo ti_right = helper.GetTypeReference(real_parameters[1].type);
if (real_parameters[1] is IDefaultOperatorNode)
il.Emit(OpCodes.Ldc_I4_0);
else
{
if (real_parameters[0] is IDefaultOperatorNode)
{
if (real_parameters[1].type is IGenericTypeInstance)
mi_right = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("get_HasValue", new Type[] { }));
else
mi_right = ti_right.tp.GetMethod("get_HasValue", new Type[] { });
}
else
{
if (real_parameters[1].type is IGenericTypeInstance) if (real_parameters[1].type is IGenericTypeInstance)
mi_right = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { })); mi_right = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { }));
else else
mi_right = ti_right.tp.GetMethod("GetValueOrDefault", new Type[] { }); mi_right = ti_right.tp.GetMethod("GetValueOrDefault", new Type[] { });
}
}
if (!(real_parameters[0] is IDefaultOperatorNode))
{
is_dot_expr = true; is_dot_expr = true;
real_parameters[0].visit(this); real_parameters[0].visit(this);
il.Emit(OpCodes.Call, mi_left); il.Emit(OpCodes.Call, mi_left);
}
if (!(real_parameters[1] is IDefaultOperatorNode))
{
is_dot_expr = true; is_dot_expr = true;
real_parameters[1].visit(this); real_parameters[1].visit(this);
il.Emit(OpCodes.Call, mi_right); il.Emit(OpCodes.Call, mi_right);
}
EmitOperator(value); EmitOperator(value);
is_dot_expr = tmp_dot; is_dot_expr = tmp_dot;
if (tmp_dot) if (tmp_dot)

9
TestSuite/nullable4.pas Normal file
View file

@ -0,0 +1,9 @@
var b: boolean := default(System.Nullable<byte>) = byte(0);
begin
assert(default(System.Nullable<byte>) = default(System.Nullable<byte>));
assert(default(System.Nullable<byte>) <> byte(0));
assert(default(System.Nullable<byte>) = nil);
assert(nil = default(System.Nullable<byte>));
assert(byte(0) <> default(System.Nullable<byte>));
assert(not b);
end.