Skip to content

Commit 1d97c06

Browse files
authored
Merge pull request #493 from exyi/fix-constructor-calls
Fix ParentFlags propagating in TryEmitNewExpression
2 parents 667b18c + 62bde56 commit 1d97c06

File tree

3 files changed

+455
-8
lines changed

3 files changed

+455
-8
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,7 +2451,7 @@ private static bool TryEmitNew(Expression expr, IReadOnlyList<PE> paramExprs, IL
24512451
CompilerFlags setup, ParentFlags parent)
24522452
#endif
24532453
{
2454-
parent |= ParentFlags.CtorCall;
2454+
var flags = ParentFlags.CtorCall;
24552455
var newExpr = (NewExpression)expr;
24562456
#if SUPPORTS_ARGUMENT_PROVIDER
24572457
var argExprs = (IArgumentProvider)newExpr;
@@ -2470,15 +2470,15 @@ private static bool TryEmitNew(Expression expr, IReadOnlyList<PE> paramExprs, IL
24702470
// see the #488 for the details.
24712471
if (argCount == 1)
24722472
{
2473-
if (!TryEmit(argExprs.GetArgument(0), paramExprs, il, ref closure, setup, parent, pars[0].ParameterType.IsByRef ? 0 : -1))
2473+
if (!TryEmit(argExprs.GetArgument(0), paramExprs, il, ref closure, setup, flags, pars[0].ParameterType.IsByRef ? 0 : -1))
24742474
return false;
24752475
}
24762476
else
24772477
{
24782478
if (!closure.ArgsContainingComplexExpression.Map.ContainsKey(newExpr))
24792479
{
24802480
for (var i = 0; i < argCount; ++i)
2481-
if (!TryEmit(argExprs.GetArgument(i), paramExprs, il, ref closure, setup, parent, pars[i].ParameterType.IsByRef ? i : -1))
2481+
if (!TryEmit(argExprs.GetArgument(i), paramExprs, il, ref closure, setup, flags, pars[i].ParameterType.IsByRef ? i : -1))
24822482
return false;
24832483
}
24842484
else
@@ -2488,7 +2488,7 @@ private static bool TryEmitNew(Expression expr, IReadOnlyList<PE> paramExprs, IL
24882488
{
24892489
var argExpr = argExprs.GetArgument(i);
24902490
var parType = pars[i].ParameterType;
2491-
if (!TryEmit(argExpr, paramExprs, il, ref closure, setup, parent, parType.IsByRef ? i : -1))
2491+
if (!TryEmit(argExpr, paramExprs, il, ref closure, setup, flags, parType.IsByRef ? i : -1))
24922492
return false;
24932493
argVars.Add(EmitStoreLocalVariable(il, parType));
24942494
}
@@ -2497,21 +2497,32 @@ private static bool TryEmitNew(Expression expr, IReadOnlyList<PE> paramExprs, IL
24972497
}
24982498
}
24992499
}
2500+
var newType = newExpr.Type;
25002501
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
25012502
if (ctor != null)
25022503
il.Demit(OpCodes.Newobj, ctor);
2503-
else if (newExpr.Type.IsValueType)
2504+
else if (newType.IsValueType)
25042505
{
2505-
ctor = newExpr.Type.GetConstructor(
2506+
ctor = newType.GetConstructor(
25062507
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
25072508
default, CallingConventions.Any, Tools.Empty<Type>(), default);
25082509
if (ctor != null)
25092510
il.Demit(OpCodes.Newobj, ctor);
25102511
else
2511-
EmitLoadLocalVariable(il, InitValueTypeVariable(il, newExpr.Type));
2512+
EmitLoadLocalVariable(il, InitValueTypeVariable(il, newType));
25122513
}
25132514
else
25142515
return false;
2516+
2517+
closure.LastEmitIsAddress = newType.IsValueType && (parent & ParentFlags.InstanceAccess) != 0 && !parent.IgnoresResult();
2518+
if (closure.LastEmitIsAddress)
2519+
{
2520+
EmitStoreAndLoadLocalVariableAddress(il, newType);
2521+
}
2522+
2523+
if (parent.IgnoresResult())
2524+
il.Demit(OpCodes.Pop);
2525+
25152526
return true;
25162527
}
25172528

@@ -5104,7 +5115,7 @@ public static bool TryEmitMemberGet(MemberExpression expr,
51045115
// if the field is not used as an index, #302
51055116
// or if the field is not accessed from the just constructed object `new Widget().DodgyValue`, #333
51065117
if (((parent & ParentFlags.InstanceAccess) != 0 &
5107-
(parent & (ParentFlags.IndexAccess | ParentFlags.Ctor)) == 0) && field.FieldType.IsValueType)
5118+
(parent & ParentFlags.IndexAccess) == 0) && field.FieldType.IsValueType)
51085119
isByAddress = true;
51095120

51105121
// we don't need to duplicate the instance if we are working with the field address to save to it directly,

test/FastExpressionCompiler.TestsRunner/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ void Run(Func<int> run, string name = null)
116116
Run(new LightExpression.UnitTests.ConvertOperatorsTests().Run);
117117
Run(new DefaultTests().Run);
118118
Run(new LightExpression.UnitTests.DefaultTests().Run);
119+
Run(new ConstructorCallTests().Run);
120+
Run(new LightExpression.UnitTests.ConstructorCallTests().Run);
119121
Run(new EqualityOperatorsTests().Run);
120122
Run(new LightExpression.UnitTests.EqualityOperatorsTests().Run);
121123
Run(new GotoTests().Run);

0 commit comments

Comments
 (0)