Skip to content

Commit

Permalink
fix C# ref return output
Browse files Browse the repository at this point in the history
  • Loading branch information
dadhi committed Jul 1, 2024
1 parent a0c9862 commit a68abf2
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 11 deletions.
20 changes: 15 additions & 5 deletions src/FastExpressionCompiler/FastExpressionCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2757,7 +2757,8 @@ public static bool TryEmitParameter(ParameterExpression paramExpr,
{
// #248 - skip the cases with `ref param.Field` were we are actually want to load the `Field` address not the `param`
// this means the parameter is the argument to the method call and not the instance in the method call or member access
if (!isPassedRef & ((parent & (ParentFlags.Call | ParentFlags.LambdaCall)) != 0) & ((parent & ParentFlags.InstanceAccess) == 0) ||
if (!isPassedRef & (parent & (ParentFlags.Call | ParentFlags.LambdaCall)) != 0 &
(parent & ParentFlags.InstanceAccess) == 0 ||
(parent & (ParentFlags.Arithmetic | ParentFlags.AssignmentRightValue)) != 0 &
(parent & (ParentFlags.MemberAccess | ParentFlags.InstanceAccess | ParentFlags.AssignmentLeftValue)) == 0)
EmitLoadIndirectlyByRef(il, paramType);
Expand Down Expand Up @@ -7266,7 +7267,7 @@ public enum EnclosedIn
/// <summary>Instructs the client code to avoid parenthesis for the generated C# code, e.g. if we have as single argument in a method</summary>
AvoidParens,
/// <summary>The instance when calling the instance method or accessing the instance member</summary>
Instance
Instance,
}

private static StringBuilder NullConstantOrDefaultToCSharpString(Type exprType, StringBuilder sb, EnclosedIn encloseIn,
Expand All @@ -7286,7 +7287,7 @@ private static StringBuilder InsertTopFFuncDefinitionOnce(StringBuilder sb) =>

internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb, EnclosedIn enclosedIn,
int lineIdent = 0, bool stripNamespace = false, Func<Type, string, string> printType = null, int identSpaces = 4,
CodePrinter.ObjectToCode notRecognizedToCode = null)
CodePrinter.ObjectToCode notRecognizedToCode = null, bool isReturnByRef = false)
{
#if LIGHT_EXPRESSION
if (e.IsCustomToCSharpString)
Expand All @@ -7310,7 +7311,11 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
return sb.Append(x.Value.ToCode(notRecognizedToCode ?? CodePrinter.DefaultNotRecognizedToCode, stripNamespace, printType));
}
case ExpressionType.Parameter:
return sb.AppendName(((ParameterExpression)e).Name, e.Type.ToCode(stripNamespace, printType), e);
{
if (isReturnByRef)
sb.Append("ref ");
return sb.AppendName(((ParameterExpression)e).Name, e.Type.ToCode(stripNamespace, printType), e);
}
case ExpressionType.New:
{
var x = (NewExpression)e;
Expand Down Expand Up @@ -7483,7 +7488,12 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
var isReturnable = bNodeType.IsReturnable();
var ignoresResult = x.ReturnType == typeof(void);
if (isReturnable & !ignoresResult)
sb.NewLineIdentCs(body, EnclosedIn.LambdaBody, lineIdent + identSpaces, stripNamespace, printType, identSpaces, notRecognizedToCode);
{
var newLineIdent = lineIdent + identSpaces;
body.ToCSharpString(sb.NewLineIdent(newLineIdent),
EnclosedIn.LambdaBody, newLineIdent, stripNamespace, printType, identSpaces,
notRecognizedToCode, lambdaMethod.ReturnType.IsByRef);
}
else
{
sb.NewLine(lineIdent, identSpaces).Append('{');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public int Run()
{
Issue413_ParameterStructIndexer();
Issue413_VariableStructIndexer();

Issue414_ReturnRefParameter();
Issue414_PassByRefParameter();

Expand Down Expand Up @@ -186,21 +186,22 @@ public void Issue415_ReturnRefParameterByRef()
var expr = Lambda<MyDelegateByRef>(p, p);

expr.PrintCSharp();
// var @cs = (MyDelegateByRef)((ref int int__32854180) => //Int32
// ref int__32854180);

var ff = expr.CompileFast(true, CompilerFlags.ThrowOnNotSupportedExpression);
ff.PrintIL();

ff.AssertOpCodes(
OpCodes.Ldarg_1,
OpCodes.Ret
);
// ff.AssertOpCodes(
// OpCodes.Ldarg_1,
// OpCodes.Ret
// );

var x = 17;
++ff(ref x);
Assert.AreEqual(18, x);
}


public static ref int ReturnRef(ref int x) => ref x;

[Test]
Expand Down

0 comments on commit a68abf2

Please sign in to comment.