// in unreachable code, for instance.
//
- if (warn)
+ bool unreachable = false;
+ if (warn && !ec.UnreachableReported) {
+ ec.UnreachableReported = true;
+ unreachable = true;
ec.Report.Warning (162, 2, loc, "Unreachable code detected");
+ }
ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
bool ok = Resolve (ec);
ec.KillFlowBranching ();
+ if (unreachable) {
+ ec.UnreachableReported = false;
+ }
+
return ok;
}
res = c;
} else {
TypeSpec type = ec.Switch.SwitchType;
- res = c.TryReduce (ec, type);
+ res = c.Reduce (ec, type);
if (res == null) {
c.Error_ValueCannotBeConverted (ec, type, true);
return false;
if (declarators != null) {
foreach (var d in declarators) {
d.Variable.CreateBuilder (ec);
- if (d.Initializer != null)
+ if (d.Initializer != null) {
+ ec.Mark (d.Variable.Location);
((ExpressionStatement) d.Initializer).EmitStatement (ec);
+ }
}
}
}
#endif
// int assignable_slots;
- bool unreachable_shown;
- bool unreachable;
-
+
public Block (Block parent, Location start, Location end)
: this (parent, 0, start, end)
{
Block prev_block = ec.CurrentBlock;
bool ok = true;
+ bool unreachable = ec.IsUnreachable;
+ bool prev_unreachable = unreachable;
ec.CurrentBlock = this;
ec.StartFlowBranching (this);
if (s is EmptyStatement)
continue;
- if (!unreachable_shown && !(s is LabeledStatement)) {
+ if (!ec.UnreachableReported && !(s is LabeledStatement)) {
ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
- unreachable_shown = true;
+ ec.UnreachableReported = true;
}
-
- Block c_block = s as Block;
- if (c_block != null)
- c_block.unreachable = c_block.unreachable_shown = true;
}
//
statements [ix] = new EmptyStatement (s.loc);
unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
- if (unreachable && s is LabeledStatement)
- throw new InternalErrorException ("should not happen");
+ if (unreachable) {
+ ec.IsUnreachable = true;
+ } else if (ec.IsUnreachable)
+ ec.IsUnreachable = false;
+ }
+
+ if (unreachable != prev_unreachable) {
+ ec.IsUnreachable = prev_unreachable;
+ ec.UnreachableReported = false;
}
while (ec.CurrentBranching is FlowBranchingLabeled)
public override bool ResolveUnreachable (BlockContext ec, bool warn)
{
- unreachable_shown = true;
- unreachable = true;
-
- if (warn)
+ bool unreachable = false;
+ if (warn && !ec.UnreachableReported) {
+ ec.UnreachableReported = true;
+ unreachable = true;
ec.Report.Warning (162, 2, loc, "Unreachable code detected");
+ }
var fb = ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
fb.CurrentUsageVector.IsUnreachable = true;
bool ok = Resolve (ec);
ec.KillFlowBranching ();
+ if (unreachable)
+ ec.UnreachableReported = false;
+
return ok;
}
// Only first storey in path will hold this reference. All children blocks will
// reference it indirectly using $ref field
//
- for (Block b = Original.Explicit.Parent; b != null; b = b.Parent) {
- var s = b.Explicit.AnonymousMethodStorey;
- if (s != null) {
- storey.HoistedThis = s.HoistedThis;
+ for (Block b = Original.Explicit; b != null; b = b.Parent) {
+ if (b.Parent != null) {
+ var s = b.Parent.Explicit.AnonymousMethodStorey;
+ if (s != null) {
+ storey.HoistedThis = s.HoistedThis;
+ break;
+ }
+ }
+
+ if (b.Explicit == b.Explicit.ParametersBlock && b.Explicit.ParametersBlock.StateMachine != null) {
+ storey.HoistedThis = b.Explicit.ParametersBlock.StateMachine.HoistedThis;
break;
}
}
// Overwrite original for comparison purposes when linking cross references
// between anonymous methods
//
- Original = source;
+ Original = source.Original;
}
#region Properties
Expression cond = null;
for (int ci = 0; ci < s.Labels.Count; ++ci) {
- var e = new Binary (Binary.Operator.Equality, value, s.Labels[ci].Converted, loc);
+ var e = new Binary (Binary.Operator.Equality, value, s.Labels[ci].Converted);
if (ci > 0) {
- cond = new Binary (Binary.Operator.LogicalOr, cond, e, loc);
+ cond = new Binary (Binary.Operator.LogicalOr, cond, e);
} else {
cond = e;
}
// fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0])
//
converted = new Conditional (new BooleanExpression (new Binary (Binary.Operator.LogicalOr,
- new Binary (Binary.Operator.Equality, initializer, new NullLiteral (loc), loc),
- new Binary (Binary.Operator.Equality, new MemberAccess (initializer, "Length"), new IntConstant (bc.BuiltinTypes, 0, loc), loc), loc)),
+ new Binary (Binary.Operator.Equality, initializer, new NullLiteral (loc)),
+ new Binary (Binary.Operator.Equality, new MemberAccess (initializer, "Length"), new IntConstant (bc.BuiltinTypes, 0, loc)))),
new NullLiteral (loc),
converted, loc);
// Add conditional call when disposing possible null variable
if (!type.IsStruct || type.IsNullableType)
- dispose = new If (new Binary (Binary.Operator.Inequality, lvr, new NullLiteral (loc), loc), dispose, dispose.loc);
+ dispose = new If (new Binary (Binary.Operator.Inequality, lvr, new NullLiteral (loc)), dispose, dispose.loc);
return dispose;
}
var idisaposable_test = new Binary (Binary.Operator.Inequality, new CompilerAssign (
dispose_variable.CreateReferenceExpression (bc, loc),
new As (lv.CreateReferenceExpression (bc, loc), new TypeExpression (dispose_variable.Type, loc), loc),
- loc), new NullLiteral (loc), loc);
+ loc), new NullLiteral (loc));
var m = bc.Module.PredefinedMembers.IDisposableDispose.Resolve (loc);