// <summary> // Creates a new flow branching which is contained in `parent'. // You should only pass non-null for the `block' argument if this block // introduces any new variables - in this case, we need to create a new // usage vector with a different size than our parent's one. // </summary> protected FlowBranching(FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) { Parent = parent; Block = block; Location = loc; Type = type; id = ++next_id; UsageVector vector; if (Block != null) { UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null; vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots); } else { vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc); } AddSibling (vector); }
public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc) { if (sibling_list.Next == null) return sibling_list; MyBitVector locals = null; bool is_unreachable = sibling_list.is_unreachable; if (!sibling_list.IsUnreachable) locals &= sibling_list.locals; for (UsageVector child = sibling_list.Next; child != null; child = child.Next) { is_unreachable &= child.is_unreachable; if (!child.IsUnreachable) locals &= child.locals; } return new UsageVector (locals, is_unreachable, null, loc); }
protected override void AddSibling (UsageVector sibling) { switch (sibling.Type) { case SiblingType.Try: try_vector = sibling; break; case SiblingType.Finally: finally_vector = sibling; break; default: throw new InvalidOperationException (); } current_vector = sibling; }
public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt) : base (next, vector) { Stmt = stmt; }
public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc) : base (next, vector) { Loc = loc; }
protected SavedOrigin (SavedOrigin next, UsageVector vector) { Next = next; Vector = vector.Clone (); }
public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) { Parent.AddReturnOrigin (vector, exit_stmt); return true; }
public override bool AddBreakOrigin (UsageVector vector, Location loc) { Parent.AddBreakOrigin (vector, loc); tc.SomeCodeFollows (); return true; }
// returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { return Parent.AddGotoOrigin (vector, goto_stmt); }
// returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) { return Parent.AddReturnOrigin (vector, stmt); }
// returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) public virtual bool AddContinueOrigin (UsageVector vector, Location loc) { return Parent.AddContinueOrigin (vector, loc); }
protected abstract void AddSibling (UsageVector uv);
// <summary> // Creates a sibling of the current usage vector. // </summary> public virtual void CreateSibling (Block block, SiblingType type) { UsageVector vector = new UsageVector ( type, Parent.CurrentUsageVector, block, Location); AddSibling (vector); Report.Debug (1, " CREATED SIBLING", CurrentUsageVector); }
public void MergeOrigins (UsageVector o_vectors) { Report.Debug (1, " MERGING BREAK ORIGINS", this); if (o_vectors == null) return; if (IsUnreachable && locals != null) locals.SetAll (true); for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) { Report.Debug (1, " MERGING BREAK ORIGIN", vector); if (vector.IsUnreachable) continue; locals &= vector.locals; is_unreachable &= vector.is_unreachable; } Report.Debug (1, " MERGING BREAK ORIGINS DONE", this); }
// <summary> // Merges a child branching. // </summary> public UsageVector MergeChild (UsageVector child, bool overwrite) { Report.Debug (2, " MERGING CHILD EFFECTS", this, child, Type); bool new_isunr = child.is_unreachable; // // We've now either reached the point after the branching or we will // never get there since we always return or always throw an exception. // // If we can reach the point after the branching, mark all locals and // parameters as initialized which have been initialized in all branches // we need to look at (see above). // if ((Type == SiblingType.SwitchSection) && !new_isunr) { Report.Error (163, Location, "Control cannot fall through from one " + "case label to another"); return child; } locals |= child.locals; // throw away un-necessary information about variables in child blocks if (locals.Count != CountLocals) locals = new MyBitVector (locals, CountLocals); if (overwrite) is_unreachable = new_isunr; else is_unreachable |= new_isunr; return child; }
public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) { vector = vector.Clone (); vector.Location = stmt.loc; vector.Next = return_origins; return_origins = vector; return false; }
public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { string name = goto_stmt.Target; LabeledStatement s = Block.LookupLabel (name); if (s != null) throw new InternalErrorException ("Shouldn't get here"); if (Parent == null) { Error_UnknownLabel (goto_stmt.loc, name, Report); return false; } int errors = Report.Errors; Parent.AddGotoOrigin (vector, goto_stmt); if (errors == Report.Errors) Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method"); return false; }
protected override void AddSibling (UsageVector sibling) { if (sibling_list != null && sibling_list.Type == SiblingType.Block) throw new InternalErrorException ("Blocks don't have sibling flow paths"); sibling.Next = sibling_list; sibling_list = sibling; }
public override bool AddContinueOrigin (UsageVector vector, Location loc) { Parent.AddContinueOrigin (vector, loc); return true; }
public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target); if (stmt == null) return Parent.AddGotoOrigin (vector, goto_stmt); // forward jump goto_stmt.SetResolvedTarget (stmt); stmt.AddUsageVector (vector); return false; }
public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { Parent.AddGotoOrigin (vector, goto_stmt); return true; }
public override bool AddBreakOrigin (UsageVector vector, Location loc) { vector = vector.Clone (); vector.Next = break_origins; break_origins = vector; return false; }
public void PropagateFinally (UsageVector finally_vector, FlowBranching parent) { if (finally_vector != null) Vector.MergeChild (finally_vector, false); DoPropagateFinally (parent); }
public override bool AddContinueOrigin (UsageVector vector, Location loc) { vector = vector.Clone (); vector.Next = continue_origins; continue_origins = vector; return false; }
public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc) : base (next, vector) { Loc = loc; }
public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt) : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc) { this.stmt = stmt; CurrentUsageVector.MergeOrigins (stmt.JumpOrigins); actual = CurrentUsageVector.Clone (); // stand-in for backward jumps CurrentUsageVector.ResetBarrier (); }
public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt) : base (next, vector) { Stmt = stmt; }
public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { if (goto_stmt.Target != stmt.Name) return Parent.AddGotoOrigin (vector, goto_stmt); // backward jump goto_stmt.SetResolvedTarget (stmt); actual.MergeOrigins (vector.Clone ()); return false; }
public override bool AddBreakOrigin (UsageVector vector, Location loc) { if (finally_vector != null) { int errors = Report.Errors; Parent.AddBreakOrigin (vector, loc); if (errors == Report.Errors) Report.Error (157, loc, "Control cannot leave the body of a finally clause"); } else { saved_origins = new BreakOrigin (saved_origins, vector, loc); } // either the loop test or a back jump will follow code stmt.SomeCodeFollows (); return true; }
public override bool AddContinueOrigin (UsageVector vector, Location loc) { Report.Error (139, loc, "No enclosing loop out of which to break or continue"); return false; }