Skip to content

Commit

Permalink
[mcs] Emit field initializer with expression tree in all user constru…
Browse files Browse the repository at this point in the history
…ctors. Fixes #18308
  • Loading branch information
marek-safar committed Mar 18, 2014
1 parent 77d00e1 commit 704ca78
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 4 deletions.
2 changes: 1 addition & 1 deletion mcs/mcs/anonymous.cs
Expand Up @@ -1267,7 +1267,7 @@ public Expression Compatible (ResolveContext ec, TypeSpec type)
throw new InternalErrorException (e, loc);
}

if (!ec.IsInProbingMode) {
if (!ec.IsInProbingMode && !etree_conversion) {
compatibles.Add (type, am ?? EmptyExpression.Null);
}

Expand Down
10 changes: 8 additions & 2 deletions mcs/mcs/assign.cs
Expand Up @@ -334,7 +334,7 @@ protected override Expression DoResolve (ResolveContext ec)

if (source == null) {
ok = false;
source = EmptyExpression.Null;
source = ErrorExpression.Instance;
}

target = target.ResolveLValue (ec, source);
Expand Down Expand Up @@ -589,6 +589,12 @@ public FieldInitializer (FieldBase mc, Expression expression, Location loc)

public int AssignmentOffset { get; private set; }

public FieldBase Field {
get {
return mc;
}
}

public override Location StartLocation {
get {
return loc;
Expand All @@ -601,8 +607,8 @@ protected override Expression DoResolve (ResolveContext rc)
if (source == null)
return null;

var bc = (BlockContext) rc;
if (resolved == null) {
var bc = (BlockContext) rc;
var ctx = new FieldInitializerContext (mc, bc);
resolved = base.DoResolve (ctx) as ExpressionStatement;
AssignmentOffset = ctx.AssignmentInfoOffset - bc.AssignmentInfoOffset;
Expand Down
14 changes: 13 additions & 1 deletion mcs/mcs/class.cs
Expand Up @@ -1010,9 +1010,20 @@ public void ResolveFieldInitializers (BlockContext ec)

for (int i = 0; i < initialized_fields.Count; ++i) {
FieldInitializer fi = initialized_fields [i];

//
// Clone before resolving otherwise when field initializer is needed
// in more than 1 constructor any resolve after the initial one would
// only took the resolved expression which is problem for expressions
// that generate extra expressions or code during Resolve phase
//
var cloned = fi.Clone (new CloneContext ());

ExpressionStatement s = fi.ResolveStatement (ec);
if (s == null)
if (s == null) {
initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
continue;
}

//
// Field is re-initialized to its default value => removed
Expand All @@ -1022,6 +1033,7 @@ public void ResolveFieldInitializers (BlockContext ec)

ec.AssignmentInfoOffset += fi.AssignmentOffset;
ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
initialized_fields [i] = (FieldInitializer) cloned;
}
}

Expand Down
1 change: 1 addition & 0 deletions mcs/mcs/convert.cs
Expand Up @@ -1467,6 +1467,7 @@ static Expression ImplicitConversionStandard (ResolveContext ec, Expression expr
return e;

source.Error_ValueCannotBeConverted (ec, target_type, false);

return null;
}

Expand Down
8 changes: 8 additions & 0 deletions mcs/mcs/ecore.cs
Expand Up @@ -5792,6 +5792,14 @@ public void SetHasAddressTaken ()
}
}

protected override void CloneTo (CloneContext clonectx, Expression target)
{
var t = (FieldExpr) target;

if (InstanceExpression != null)
t.InstanceExpression = InstanceExpression.Clone (clonectx);
}

public override Expression CreateExpressionTree (ResolveContext ec)
{
return CreateExpressionTree (ec, true);
Expand Down
4 changes: 4 additions & 0 deletions mcs/mcs/expression.cs
Expand Up @@ -9999,6 +9999,10 @@ public EmptyExpression (TypeSpec t)
loc = Location.Null;
}

protected override void CloneTo (CloneContext clonectx, Expression target)
{
}

public override bool ContainsEmitWithAwait ()
{
return false;
Expand Down
30 changes: 30 additions & 0 deletions mcs/tests/gtest-etree-30.cs
@@ -0,0 +1,30 @@
using System;
using System.Linq.Expressions;

public sealed class C
{
public C ()
{
}

public C (Action<object, object> tappedCallback)
{
}

public readonly string TappedCallbackProperty = Create<C, Action<object, object>> (o => o.TappedCallback);

public Action<object, object> TappedCallback {
get;
set;
}

public static string Create<T1, T2> (Expression<Func<T1, T2>> getter)
{
return null;
}

public static void Main ()
{
new C (null);
}
}

0 comments on commit 704ca78

Please sign in to comment.