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);
			}
		}
		public FlowBranchingTryFinally (FlowBranching parent,
					       ExceptionStatement stmt)
			: base (parent, BranchingType.Exception, SiblingType.Try,
				null, stmt.loc)
		{
			this.stmt = stmt;
		}
			protected override void DoPropagateFinally (FlowBranching parent)
			{
				parent.AddGotoOrigin (Vector, Stmt);
			}
			protected override void DoPropagateFinally (FlowBranching parent)
			{
				parent.AddContinueOrigin (Vector, Loc);
			}
			public void PropagateFinally (UsageVector finally_vector, FlowBranching parent)
			{
				if (finally_vector != null)
					Vector.MergeChild (finally_vector, false);
				DoPropagateFinally (parent);
			}
			protected abstract void DoPropagateFinally (FlowBranching parent);
		public FlowBranchingAsync (FlowBranching parent, AsyncInitializer async_init)
			: base (parent, BranchingType.Block, SiblingType.Try, null, async_init.Location)
		{
			this.async_init = async_init;
		}
		public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt)
			: base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc)
		{
			this.tc = stmt;
		}
		public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt)
			: base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc)
		{
		}
		public FlowBranchingIterator (FlowBranching parent, Iterator iterator)
			: base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location)
		{
			this.iterator = iterator;
		}
		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 FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
			: base (parent, type, stype, block, loc)
		{ }
		public UsageVector MergeChild (FlowBranching child)
		{
			return CurrentUsageVector.MergeChild (child.Merge (), true);
 		}
		// <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);
		}