public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc) { switch (type) { case BranchingType.Exception: case BranchingType.Labeled: case BranchingType.Toplevel: case BranchingType.TryCatch: throw new InvalidOperationException (); case BranchingType.Switch: return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc); case BranchingType.Block: return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc); case BranchingType.Loop: return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc); case BranchingType.Embedded: return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc); default: return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc); } }
// <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); }
protected override void DoPropagateFinally (FlowBranching parent) { parent.AddContinueOrigin (Vector, Loc); }
// <summary> // A struct's constructor must always assign all fields. // This method checks whether it actually does so. // </summary> public bool IsFullyInitialized (FlowBranching branching, VariableInfo vi, Location loc) { if (struct_info == null) return true; bool ok = true; for (int i = 0; i < struct_info.Count; i++) { FieldInfo field = struct_info.Fields [i]; if (!branching.IsFieldAssigned (vi, field.Name)) { FieldBase fb = TypeManager.GetField (field); if (fb != null && (fb.ModFlags & Modifiers.BACKING_FIELD) != 0) { Report.Error (843, loc, "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling default contructor", fb.GetSignatureForError ()); } else { Report.Error (171, loc, "Field `{0}' must be fully assigned before control leaves the constructor", TypeManager.GetFullNameSignature (field)); } ok = false; } } return ok; }
public void PropagateFinally (UsageVector finally_vector, FlowBranching parent) { if (finally_vector != null) Vector.MergeChild (finally_vector, false); DoPropagateFinally (parent); }
public FlowBranchingIterator StartFlowBranching (StateMachineInitializer iterator, FlowBranching parent) { FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator); current_flow_branching = branching; return branching; }
// <summary> // Ends a code branching. Merges the state of locals and parameters // from all the children of the ending branching. // </summary> public bool EndFlowBranching () { FlowBranching old = current_flow_branching; current_flow_branching = current_flow_branching.Parent; FlowBranching.UsageVector vector = current_flow_branching.MergeChild (old); return vector.IsUnreachable; }
// <summary> // Starts a new code branching. This inherits the state of all local // variables and parameters from the current branching. // </summary> public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc) { current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc); return current_flow_branching; }
public FlowBranchingTryCatch StartFlowBranching (TryCatch stmt) { FlowBranchingTryCatch branching = new FlowBranchingTryCatch (CurrentBranching, stmt); current_flow_branching = branching; return branching; }
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 FlowBranchingIterator (FlowBranching parent, Iterator iterator) : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location) { this.iterator = iterator; }
public UsageVector MergeChild (FlowBranching child) { return CurrentUsageVector.MergeChild (child.Merge (), true); }
public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) : base (parent, type, stype, block, loc) { }
public void AddUsageVector (FlowBranching.UsageVector vector) { vector = vector.Clone (); vector.Next = vectors; vectors = vector; }
public bool Resolve (FlowBranching parent, BlockContext rc, IMethodData md) { if (resolved) return true; resolved = true; if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) flags |= Flags.IsExpressionTree; try { ResolveMeta (rc); using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) { FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent); if (!Resolve (rc)) return false; unreachable = top_level.End (); } } catch (Exception e) { if (e is CompletionResult || rc.Report.IsDisabled) throw; if (rc.CurrentBlock != null) { rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message); } else { rc.Report.Error (587, "Internal compiler error: {0}", e.Message); } if (Report.DebugFlags > 0) throw; } if (rc.ReturnType != TypeManager.void_type && !unreachable) { if (rc.CurrentAnonymousMethod == null) { // FIXME: Missing FlowAnalysis for generated iterator MoveNext method if (md is IteratorMethod) { unreachable = true; } else { rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ()); return false; } } else { rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'", rc.CurrentAnonymousMethod.GetSignatureForError ()); return false; } } return true; }
// <summary> // Check whether all `out' parameters have been assigned. // </summary> public void CheckOutParameters (FlowBranching.UsageVector vector, Location loc) { if (vector.IsUnreachable) return; int n = parameter_info == null ? 0 : parameter_info.Length; for (int i = 0; i < n; i++) { VariableInfo var = parameter_info[i].VariableInfo; if (var == null) continue; if (vector.IsAssigned (var, false)) continue; TopBlock.Report.Error (177, loc, "The out parameter `{0}' must be assigned to before control leaves the current method", var.Name); } }
protected override void DoPropagateFinally (FlowBranching parent) { parent.AddGotoOrigin (Vector, Stmt); }
public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt) : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc) { }
public FlowBranchingTryFinally (FlowBranching parent, ExceptionStatement stmt) : base (parent, BranchingType.Exception, SiblingType.Try, null, stmt.loc) { this.stmt = stmt; }
public FlowBranchingLabeled StartFlowBranching (LabeledStatement stmt) { FlowBranchingLabeled branching = new FlowBranchingLabeled (CurrentBranching, stmt); current_flow_branching = branching; return branching; }
// <summary> // Starts a new code branching for block `block'. // </summary> public FlowBranching StartFlowBranching (Block block) { Set (Options.DoFlowAnalysis); current_flow_branching = FlowBranching.CreateBranching ( CurrentBranching, FlowBranching.BranchingType.Block, block, block.StartLocation); return current_flow_branching; }
public FlowBranchingAsync StartFlowBranching (AsyncInitializer asyncBody, FlowBranching parent) { var branching = new FlowBranchingAsync (parent, asyncBody); current_flow_branching = branching; return branching; }
public FlowBranchingTryFinally StartFlowBranching (TryFinallyBlock stmt) { FlowBranchingTryFinally branching = new FlowBranchingTryFinally (CurrentBranching, stmt); current_flow_branching = branching; return branching; }
public FlowBranchingException StartFlowBranching (ExceptionStatement stmt) { FlowBranchingException branching = new FlowBranchingException (CurrentBranching, stmt); current_flow_branching = branching; return branching; }
public FlowBranchingIterator StartFlowBranching (Iterator iterator, FlowBranching parent) { FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator); current_flow_branching = branching; return branching; }
public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt) : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc) { this.tc = stmt; }
public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent) { FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt); current_flow_branching = branching; return branching; }
public FlowBranchingAsync (FlowBranching parent, AsyncInitializer async_init) : base (parent, BranchingType.Block, SiblingType.Try, null, async_init.Location) { this.async_init = async_init; }
// <summary> // Kills the current code branching. This throws away any changed state // information and should only be used in case of an error. // </summary> // FIXME: this is evil public void KillFlowBranching () { current_flow_branching = current_flow_branching.Parent; }
protected abstract void DoPropagateFinally (FlowBranching parent);