var da_false = new DefiniteAssignmentBitSet (fc.DefiniteAssignmentOnFalse);
fc.DefiniteAssignment = fc.DefiniteAssignmentOnTrue;
+ var labels = fc.CopyLabelStack ();
var res = TrueStatement.FlowAnalysis (fc);
+ fc.SetLabelStack (labels);
+
if (FalseStatement == null) {
+
var c = expr as Constant;
if (c != null && !c.IsDefaultValue)
return true_returns;
if (true_returns) {
fc.DefiniteAssignment = da_false;
- return FalseStatement.FlowAnalysis (fc);
+
+ res = FalseStatement.FlowAnalysis (fc);
+ fc.SetLabelStack (labels);
+ return res;
}
var da_true = fc.DefiniteAssignment;
fc.DefiniteAssignment = da_false;
+
res &= FalseStatement.FlowAnalysis (fc);
+ fc.SetLabelStack (labels);
+
if (!TrueStatement.IsUnreachable) {
if (false_returns || FalseStatement.IsUnreachable)
fc.DefiniteAssignment = da_true;
public override void Emit (EmitContext ec)
{
+ if (!Variable.IsUsed)
+ ec.Report.Warning (219, 3, loc, "The constant `{0}' is never used", Variable.Name);
+
// Nothing to emit, not even sequence point
}
}
}
+ public bool IsUsed {
+ get {
+ return (flags & Flags.Used) != 0;
+ }
+ }
+
public bool IsFixed {
get {
return (flags & Flags.FixedVariable) != 0;
public Expression CreateReferenceExpression (ResolveContext rc, Location loc)
{
- if (IsConstant && const_value != null)
+ if (IsConstant && const_value != null) {
+ SetIsUsed ();
return Constant.CreateConstantFromValue (Type, const_value.GetValue (), loc);
+ }
return new LocalVariableReference (this, loc);
}
AwaitBlock = 1 << 13,
FinallyBlock = 1 << 14,
CatchBlock = 1 << 15,
+ HasReferenceToStoreyForInstanceLambdas = 1 << 16,
Iterator = 1 << 20,
NoFlowAnalysis = 1 << 21,
InitializationEmitted = 1 << 22
//
storey.CreateContainer ();
storey.DefineContainer ();
+ storey.ExpandBaseInterfaces ();
if (Original.Explicit.HasCapturedThis && Original.ParametersBlock.TopBlock.ThisReferencesFromChildrenBlock != null) {
break;
}
}
-
+
//
// We are the first storey on path and 'this' has to be hoisted
//
//
// If we are state machine with no parent. We can hook into parent without additional
- // reference and capture this directly
+ // reference and capture this directly
//
ExplicitBlock parent_storey_block = pb;
while (parent_storey_block.Parent != null) {
#region Properties
+ public bool HasReferenceToStoreyForInstanceLambdas {
+ get {
+ return (flags & Flags.HasReferenceToStoreyForInstanceLambdas) != 0;
+ }
+ set {
+ flags = value ? flags | Flags.HasReferenceToStoreyForInstanceLambdas : flags & ~Flags.HasReferenceToStoreyForInstanceLambdas;
+ }
+ }
+
public bool IsAsync {
get {
return (flags & Flags.HasAsyncModifier) != 0;
continue;
}
- if (constant_label != null && constant_label != sl)
+ if (section_rc.IsUnreachable) {
+ //
+ // Common case. Previous label section end is unreachable as
+ // it ends with break, return, etc. For next section revert
+ // to reachable again unless we have constant switch block
+ //
+ section_rc = constant_label != null && constant_label != sl ?
+ Reachability.CreateUnreachable () :
+ new Reachability ();
+ } else if (prev_label != null) {
+ //
+ // Error case as control cannot fall through from one case label
+ //
+ sl.SectionStart = false;
+ s = new MissingBreak (prev_label);
+ s.MarkReachable (rc);
+ block.Statements.Insert (i - 1, s);
+ ++i;
+ } else if (constant_label != null && constant_label != sl) {
+ //
+ // Special case for the first unreachable label in constant
+ // switch block
+ //
section_rc = Reachability.CreateUnreachable ();
- else if (section_rc.IsUnreachable) {
- section_rc = new Reachability ();
- } else {
- if (prev_label != null) {
- sl.SectionStart = false;
- s = new MissingBreak (prev_label);
- s.MarkReachable (rc);
- block.Statements.Insert (i - 1, s);
- ++i;
- }
}
prev_label = sl;
ec.EmitInt (first_resume_pc);
ec.Emit (OpCodes.Sub);
- var labels = new Label[resume_points.Count - System.Math.Max (first_catch_resume_pc, 0)];
+ var labels = new Label [first_catch_resume_pc > 0 ? first_catch_resume_pc : resume_points.Count];
for (int i = 0; i < labels.Length; ++i)
labels[i] = resume_points[i].PrepareForEmit (ec);
ec.Emit (OpCodes.Switch, labels);
ec.Emit (OpCodes.Stloc, temp);
var exception_field = ec.GetTemporaryField (type);
+ exception_field.AutomaticallyReuse = false;
ec.EmitThis ();
ec.Emit (OpCodes.Ldloc, temp);
exception_field.EmitAssignFromStack (ec);
ec.Emit (OpCodes.Throw);
ec.MarkLabel (skip_throw);
- exception_field.IsAvailableForReuse = true;
+ exception_field.PrepareCleanup (ec);
EmitUnwindFinallyTable (ec);
}