return;
}
+ a.And (b, do_break);
+ }
+
+ public void And (Reachability b, bool do_break)
+ {
//
// `break' does not "break" in a Switch or a LoopBlock
//
- bool a_breaks = do_break && a.AlwaysBreaks;
+ bool a_breaks = do_break && AlwaysBreaks;
bool b_breaks = do_break && b.AlwaysBreaks;
bool a_has_barrier, b_has_barrier;
// This is the normal case: the code following a barrier
// cannot be reached.
//
- a_has_barrier = a.AlwaysHasBarrier;
+ a_has_barrier = AlwaysHasBarrier;
b_has_barrier = b.AlwaysHasBarrier;
} else {
//
// Special case for Switch and LoopBlocks: we can reach the
// code after the barrier via the `break'.
//
- a_has_barrier = !a.AlwaysBreaks && a.AlwaysHasBarrier;
+ a_has_barrier = !AlwaysBreaks && AlwaysHasBarrier;
b_has_barrier = !b.AlwaysBreaks && b.AlwaysHasBarrier;
}
- bool a_unreachable = a_breaks || a.AlwaysThrows || a_has_barrier;
+ bool a_unreachable = a_breaks || AlwaysThrows || a_has_barrier;
bool b_unreachable = b_breaks || b.AlwaysThrows || b_has_barrier;
//
// Do all code paths always return ?
//
- if (a.AlwaysReturns) {
+ if (AlwaysReturns) {
if (b.AlwaysReturns || b_unreachable)
- a.returns = FlowReturns.Always;
+ returns = FlowReturns.Always;
else
- a.returns = FlowReturns.Sometimes;
+ returns = FlowReturns.Sometimes;
} else if (b.AlwaysReturns) {
- if (a.AlwaysReturns || a_unreachable)
- a.returns = FlowReturns.Always;
+ if (AlwaysReturns || a_unreachable)
+ returns = FlowReturns.Always;
else
- a.returns = FlowReturns.Sometimes;
- } else if (!a.MayReturn) {
+ returns = FlowReturns.Sometimes;
+ } else if (!MayReturn) {
if (b.MayReturn)
- a.returns = FlowReturns.Sometimes;
+ returns = FlowReturns.Sometimes;
else
- a.returns = FlowReturns.Never;
+ returns = FlowReturns.Never;
} else if (!b.MayReturn) {
- if (a.MayReturn)
- a.returns = FlowReturns.Sometimes;
+ if (MayReturn)
+ returns = FlowReturns.Sometimes;
else
- a.returns = FlowReturns.Never;
+ returns = FlowReturns.Never;
}
- a.breaks = AndFlowReturns (a.breaks, b.breaks);
- a.throws = AndFlowReturns (a.throws, b.throws);
- a.barrier = AndFlowReturns (a.barrier, b.barrier);
+ breaks = AndFlowReturns (breaks, b.breaks);
+ throws = AndFlowReturns (throws, b.throws);
+ barrier = AndFlowReturns (barrier, b.barrier);
if (a_unreachable && b_unreachable)
- a.barrier = FlowReturns.Always;
+ barrier = FlowReturns.Always;
else if (a_unreachable || b_unreachable)
- a.barrier = FlowReturns.Sometimes;
+ barrier = FlowReturns.Sometimes;
else
- a.barrier = FlowReturns.Never;
+ barrier = FlowReturns.Never;
}
public void Or (Reachability b)
throw new InvalidOperationException ();
case BranchingType.Switch:
- return new FlowBranchingBlock (parent, type, SiblingType.SwitchSection, block, loc);
+ return new FlowBranchingSwitch (parent, block, loc);
case BranchingType.SwitchSection:
return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
// then we do always return (or stay in the
// loop forever).
new_r.SetReturns ();
- }
+ }
new_r.SetBarrier ();
- } else {
- if (new_r.Returns == FlowReturns.Always) {
- // We're either finite or we may leave the loop.
- new_r.SetReturnsSometimes ();
- }
- if (new_r.Throws == FlowReturns.Always) {
- // We're either finite or we may leave the loop.
- new_r.SetThrowsSometimes ();
- }
- }
+ }
+
+ if (may_leave_loop)
+ new_r.ResetBarrier ();
} else if (branching.Type == BranchingType.Switch) {
if (new_r.MayBreak || new_r.MayReturn)
new_r.ResetBarrier ();
if (result.ParameterVector != null)
parameters.Or (result.ParameterVector);
- reachability.Or (new_r);
+ if ((branching.Type == BranchingType.Block) && branching.Block.Implicit)
+ reachability = new_r.Clone ();
+ else
+ reachability.Or (new_r);
Report.Debug (2, " MERGING CHILD DONE", this, result,
new_r, reachability);
for (UsageVector vector = o_vectors; vector != null;
vector = vector.Next) {
- Report.Debug (1, " MERGING JUMP ORIGIN", vector);
+ Report.Debug (1, " MERGING JUMP ORIGIN", vector,
+ first, locals, vector.Locals);
if (first) {
if (locals != null && vector.Locals != null)
- locals.Or (vector.locals);
+ locals.Or (vector.locals);
if (parameters != null)
parameters.Or (vector.parameters);
first = false;
} else {
- if (locals != null && vector.Locals != null)
- locals.And (vector.locals);
- if (parameters != null)
- parameters.And (vector.parameters);
- }
+ if (locals != null)
+ locals.And (vector.locals);
+ if (parameters != null)
+ parameters.And (vector.parameters);
+ }
Reachability.And (ref reachability, vector.Reachability, true);
+
+ Report.Debug (1, " MERGING JUMP ORIGIN #1", vector);
}
Report.Debug (1, " MERGING JUMP ORIGINS DONE", this);
Report.Debug (1, " MERGING FINALLY ORIGIN DONE", this);
}
- public void MergeBreakOrigins (UsageVector o_vectors)
+ public void MergeBreakOrigins (FlowBranching branching, UsageVector o_vectors)
{
Report.Debug (1, " MERGING BREAK ORIGINS", this);
if (o_vectors == null)
return;
- bool first = true;
+ bool first = branching.Infinite;
for (UsageVector vector = o_vectors; vector != null;
vector = vector.Next) {
- Report.Debug (1, " MERGING BREAK ORIGIN", vector);
+ Report.Debug (1, " MERGING BREAK ORIGIN", vector, first);
if (first) {
if (locals != null && vector.Locals != null)
if (parameters != null)
parameters.And (vector.parameters);
}
+
+ reachability.And (vector.Reachability, false);
}
Report.Debug (1, " MERGING BREAK ORIGINS DONE", this);
if (var.IsAssigned (parameters))
continue;
- Report.Error (177, loc, "The out parameter `" +
- var.Name + "' must be " +
- "assigned before control leaves the current method.");
+ Report.Error (177, loc, "The out parameter `{0}' must be assigned to before control leaves the current method",
+ var.Name);
}
}
throw new NotSupportedException ();
UsageVector vector = new UsageVector (
- SiblingType.Conditional, null, Block, Location,
+ SiblingType.Block, null, Block, Location,
param_map.Length, local_map.Length);
UsageVector result = vector.MergeChild (this);
return false;
}
- //
- // Checks whether we're in a `catch' block.
- //
- public virtual bool InCatch ()
+ public virtual bool InTryWithCatch ()
{
if (Parent != null)
- return Parent.InCatch ();
- else
- return false;
- }
-
- //
- // Checks whether we're in a `finally' block.
- //
- public virtual bool InFinally (bool is_return)
- {
- if (!is_return &&
- ((Type == BranchingType.Loop) || (Type == BranchingType.Switch)))
- return false;
- else if (Parent != null)
- return Parent.InFinally (is_return);
- else
- return false;
+ return Parent.InTryWithCatch ();
+ return false;
}
public virtual bool InLoop ()
{
UsageVector vector = base.Merge ();
- vector.MergeBreakOrigins (break_origins);
+ vector.MergeBreakOrigins (this, break_origins);
+
+ return vector;
+ }
+ }
+
+ public class FlowBranchingSwitch : FlowBranchingBlock
+ {
+ UsageVector break_origins;
+
+ public FlowBranchingSwitch (FlowBranching parent, Block block, Location loc)
+ : base (parent, BranchingType.Switch, SiblingType.SwitchSection, block, loc)
+ { }
+
+ public override void AddBreakVector (UsageVector vector)
+ {
+ vector = vector.Clone ();
+ vector.Next = break_origins;
+ break_origins = vector;
+ }
+
+ protected override UsageVector Merge ()
+ {
+ UsageVector vector = base.Merge ();
+
+ vector.MergeBreakOrigins (this, break_origins);
return vector;
}
UsageVector finally_vector;
UsageVector finally_origins;
bool emit_finally;
- bool in_try;
public FlowBranchingException (FlowBranching parent,
ExceptionStatement stmt)
if (sibling.Type == SiblingType.Try) {
sibling.Next = catch_vectors;
catch_vectors = sibling;
- in_try = true;
} else if (sibling.Type == SiblingType.Catch) {
sibling.Next = catch_vectors;
catch_vectors = sibling;
- in_try = false;
} else if (sibling.Type == SiblingType.Finally) {
sibling.MergeFinallyOrigins (finally_origins);
finally_vector = sibling;
- in_try = false;
} else
throw new InvalidOperationException ();
return finally_vector == null;
}
- public override bool InCatch ()
+ public override bool InTryWithCatch ()
{
- return !in_try && (finally_vector == null);
- }
+ if (finally_vector == null) {
+ Try t = stmt as Try;
+ if (t != null && t.HasCatch)
+ return true;
+ }
- public override bool InFinally (bool is_return)
- {
- return finally_vector != null;
+ if (Parent != null)
+ return Parent.InTryWithCatch ();
+
+ return false;
}
public override bool BreakCrossesTryCatchBoundary ()
return s;
if (finally_vector != null) {
- Report.Error (
- 157, loc, "Control can not leave the body " +
- "of the finally block");
+ Report.Error (157, loc,
+ "Control cannot leave the body of a finally clause");
return null;
}
if (!branching.IsFieldAssigned (vi, field.Name)) {
Report.Error (171, loc,
- "Field `" + TypeManager.CSharpName (Type) +
- "." + field.Name + "' must be fully initialized " +
- "before control leaves the constructor");
+ "Field `{0}' must be fully assigned before control leaves the constructor",
+ TypeManager.GetFullNameSignature (field));
ok = false;
}
}
if (type is TypeBuilder) {
TypeContainer tc = TypeManager.LookupTypeContainer (type);
- ArrayList fields = tc.Fields;
+ ArrayList fields = null;
+ if (tc != null)
+ fields = tc.Fields;
ArrayList public_fields = new ArrayList ();
ArrayList non_public_fields = new ArrayList ();
if (fields != null) {
- foreach (Field field in fields) {
+ foreach (FieldMember field in fields) {
if ((field.ModFlags & Modifiers.STATIC) != 0)
continue;
if ((field.ModFlags & Modifiers.PUBLIC) != 0)
field_hash.Add (field.Name, ++Length);
else if (sinfo [i].InTransit) {
Report.Error (523, String.Format (
- "Struct member '{0}.{1}' of type '{2}' causes " +
+ "Struct member `{0}.{1}' of type `{2}' causes " +
"a cycle in the structure layout",
type, field.Name, sinfo [i].Type));
sinfo [i] = null;
public bool IsAssigned (EmitContext ec)
{
- return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
+ return !ec.DoFlowAnalysis ||
+ ec.OmitStructFlowAnalysis && TypeInfo.IsStruct ||
+ ec.CurrentBranching.IsAssigned (this);
}
public bool IsAssigned (EmitContext ec, Location loc)
public bool IsFieldAssigned (EmitContext ec, string name, Location loc)
{
- if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsFieldAssigned (this, name))
+ if (!ec.DoFlowAnalysis ||
+ ec.OmitStructFlowAnalysis && TypeInfo.IsStruct ||
+ ec.CurrentBranching.IsFieldAssigned (this, name))
return true;
Report.Error (170, loc,
// </summary>
public void And (MyBitVector new_vector)
{
- BitArray new_array = new_vector.Vector;
+ BitArray new_array;
+
+ if (new_vector != null)
+ new_array = new_vector.Vector;
+ else
+ new_array = new BitArray (Count, false);
initialize_vector ();