}
}
+ public override Location StartLocation {
+ get {
+ return target.StartLocation;
+ }
+ }
+
public override bool ContainsEmitWithAwait ()
{
return target.ContainsEmitWithAwait () || source.ContainsEmitWithAwait ();
if (source == null) {
ok = false;
- source = EmptyExpression.Null;
+ source = ErrorExpression.Instance;
}
target = target.ResolveLValue (ec, source);
return this;
}
-#if NET_4_0 || MONODROID
public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx)
{
var tassign = target as IDynamicAssign;
return System.Linq.Expressions.Expression.Assign (target_object, source_object);
}
-#endif
+
protected virtual Expression ResolveConversions (ResolveContext ec)
{
source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location);
Emit (ec, true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ source.FlowAnalysis (fc);
+
+ if (target is ArrayAccess || target is IndexerExpr) {
+ target.FlowAnalysis (fc);
+ return;
+ }
+
+ var pe = target as PropertyExpr;
+ if (pe != null && !pe.IsAutoPropertyAccess)
+ target.FlowAnalysis (fc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
Assign _target = (Assign) t;
return this;
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ base.FlowAnalysis (fc);
+
+ var vr = target as VariableReference;
+ if (vr != null) {
+ if (vr.VariableInfo != null)
+ fc.SetVariableAssigned (vr.VariableInfo);
+
+ return;
+ }
+
+ var fe = target as FieldExpr;
+ if (fe != null) {
+ fe.SetFieldAssigned (fc);
+ return;
+ }
+
+ var pe = target as PropertyExpr;
+ if (pe != null) {
+ pe.SetBackingFieldAssigned (fc);
+ return;
+ }
+
+ var td = target as TupleDeconstruct;
+ if (td != null) {
+ td.SetGeneratedFieldAssigned (fc);
+ return;
+ }
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return source.MarkReachable (rc);
+ }
}
public class RuntimeExplicitAssign : Assign
// share same constructor (block) for expression trees resolve but
// they have they own resolve scope
//
- sealed class FieldInitializerContext : ResolveContext
+ sealed class FieldInitializerContext : BlockContext
{
- ExplicitBlock ctor_block;
+ readonly ExplicitBlock ctor_block;
- public FieldInitializerContext (IMemberContext mc, ResolveContext constructorContext)
- : base (mc, Options.FieldInitializerScope | Options.ConstructorScope)
+ public FieldInitializerContext (IMemberContext mc, BlockContext constructorContext)
+ : base (mc, null, constructorContext.ReturnType)
{
+ flags |= Options.FieldInitializerScope | Options.ConstructorScope;
this.ctor_block = constructorContext.CurrentBlock.Explicit;
+
+ if (ctor_block.IsCompilerGenerated)
+ CurrentBlock = ctor_block;
}
public override ExplicitBlock ConstructorBlock {
- get {
- return ctor_block;
- }
+ get {
+ return ctor_block;
+ }
}
}
// Keep resolved value because field initializers have their own rules
//
ExpressionStatement resolved;
- IMemberContext mc;
+ FieldBase mc;
- public FieldInitializer (FieldSpec spec, Expression expression, IMemberContext mc)
- : base (new FieldExpr (spec, expression.Location), expression, expression.Location)
+ public FieldInitializer (FieldBase mc, Expression expression, Location loc)
+ : base (new FieldExpr (mc.Spec, expression.Location), expression, loc)
{
this.mc = mc;
- if (!spec.IsStatic)
+ if (!mc.IsStatic)
((FieldExpr)target).InstanceExpression = new CompilerGeneratedThis (mc.CurrentType, expression.Location);
}
- protected override Expression DoResolve (ResolveContext ec)
+ public int AssignmentOffset { get; private set; }
+
+ public FieldBase Field {
+ get {
+ return mc;
+ }
+ }
+
+ public override Location StartLocation {
+ get {
+ return loc;
+ }
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
{
// Field initializer can be resolved (fail) many times
if (source == null)
return null;
if (resolved == null) {
- var ctx = new FieldInitializerContext (mc, ec);
+ var bc = (BlockContext) rc;
+ var ctx = new FieldInitializerContext (mc, bc);
resolved = base.DoResolve (ctx) as ExpressionStatement;
+ AssignmentOffset = ctx.AssignmentInfoOffset - bc.AssignmentInfoOffset;
}
return resolved;
else
base.EmitStatement (ec);
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ source.FlowAnalysis (fc);
+ ((FieldExpr) target).SetFieldAssigned (fc);
+ }
public bool IsDefaultInitializer {
get {
}
}
+ class PrimaryConstructorAssign : SimpleAssign
+ {
+ readonly Field field;
+ readonly Parameter parameter;
+
+ public PrimaryConstructorAssign (Field field, Parameter parameter)
+ : base (null, null, parameter.Location)
+ {
+ this.field = field;
+ this.parameter = parameter;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ target = new FieldExpr (field, loc);
+ source = rc.CurrentBlock.ParametersBlock.GetParameterInfo (parameter).CreateReferenceExpression (rc, loc);
+ return base.DoResolve (rc);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ using (ec.With (BuilderContext.Options.OmitDebugInfo, true)) {
+ base.EmitStatement (ec);
+ }
+ }
+ }
+
//
// This class is used for compound assignments.
//
this.loc = child.Location;
}
+ public bool RequiresEmitWithAwait { get; set; }
+
public override bool ContainsEmitWithAwait ()
{
- return child.ContainsEmitWithAwait ();
+ return RequiresEmitWithAwait || child.ContainsEmitWithAwait ();
}
public override Expression CreateExpressionTree (ResolveContext ec)
Expression right;
Expression left;
- public CompoundAssign (Binary.Operator op, Expression target, Expression source, Location loc)
- : base (target, source, loc)
+ public CompoundAssign (Binary.Operator op, Expression target, Expression source)
+ : base (target, source, target.Location)
{
right = source;
this.op = op;
}
- public CompoundAssign (Binary.Operator op, Expression target, Expression source, Expression left, Location loc)
- : this (op, target, source, loc)
+ public CompoundAssign (Binary.Operator op, Expression target, Expression source, Expression left)
+ : this (op, target, source)
{
this.left = left;
}
if (left == null)
left = new TargetExpression (target);
- source = new Binary (op, left, right, true, loc);
+ source = new Binary (op, left, right, true);
if (target is DynamicMemberAssignable) {
Arguments targs = ((DynamicMemberAssignable) target).Arguments;
return base.DoResolve (ec);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ target.FlowAnalysis (fc);
+ source.FlowAnalysis (fc);
+ }
+
protected override Expression ResolveConversions (ResolveContext ec)
{
//
// Otherwise, if the selected operator is a predefined operator
//
Binary b = source as Binary;
- if (b == null && source is ReducedExpression)
- b = ((ReducedExpression) source).OriginalExpression as Binary;
+ if (b == null) {
+ if (source is ReducedExpression)
+ b = ((ReducedExpression) source).OriginalExpression as Binary;
+ else if (source is ReducedExpression.ReducedConstantExpression) {
+ b = ((ReducedExpression.ReducedConstantExpression) source).OriginalExpression as Binary;
+ } else if (source is Nullable.LiftedBinaryOperator) {
+ var po = ((Nullable.LiftedBinaryOperator) source);
+ if (po.UserOperator == null)
+ b = po.Binary;
+ } else if (source is TypeCast) {
+ b = ((TypeCast) source).Child as Binary;
+ }
+ }
if (b != null) {
//