condition tests passes
[mono.git] / mcs / mcs / flowanalysis.cs
1 //
2 // flowanalyis.cs: The control flow analysis code
3 //
4 // Author:
5 //   Martin Baulig (martin@ximian.com)
6 //   Raja R Harinath (rharinath@novell.com)
7 //
8 // (C) 2001, 2002, 2003 Ximian, Inc.
9 //
10
11 using System;
12 using System.Text;
13 using System.Collections;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Diagnostics;
17
18 namespace Mono.CSharp
19 {
20         // <summary>
21         //   A new instance of this class is created every time a new block is resolved
22         //   and if there's branching in the block's control flow.
23         // </summary>
24         public abstract class FlowBranching
25         {
26                 // <summary>
27                 //   The type of a FlowBranching.
28                 // </summary>
29                 public enum BranchingType : byte {
30                         // Normal (conditional or toplevel) block.
31                         Block,
32
33                         // Conditional.
34                         Conditional,
35
36                         // A loop block.
37                         Loop,
38
39                         // The statement embedded inside a loop
40                         Embedded,
41
42                         // part of a block headed by a jump target
43                         Labeled,
44
45                         // Try/Catch block.
46                         Exception,
47
48                         // Switch block.
49                         Switch,
50
51                         // Switch section.
52                         SwitchSection,
53
54                         // The toplevel block of a function
55                         Toplevel
56                 }
57
58                 // <summary>
59                 //   The type of one sibling of a branching.
60                 // </summary>
61                 public enum SiblingType : byte {
62                         Block,
63                         Conditional,
64                         SwitchSection,
65                         Try,
66                         Catch,
67                         Finally
68                 }
69
70                 public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc)
71                 {
72                         switch (type) {
73                         case BranchingType.Exception:
74                         case BranchingType.Labeled:
75                         case BranchingType.Toplevel:
76                                 throw new InvalidOperationException ();
77
78                         case BranchingType.Switch:
79                                 return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc);
80
81                         case BranchingType.SwitchSection:
82                                 return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
83
84                         case BranchingType.Block:
85                                 return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
86
87                         case BranchingType.Loop:
88                                 return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc);
89
90                         case BranchingType.Embedded:
91                                 return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc);
92
93                         default:
94                                 return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc);
95                         }
96                 }
97
98                 // <summary>
99                 //   The type of this flow branching.
100                 // </summary>
101                 public readonly BranchingType Type;
102
103                 // <summary>
104                 //   The block this branching is contained in.  This may be null if it's not
105                 //   a top-level block and it doesn't declare any local variables.
106                 // </summary>
107                 public readonly Block Block;
108
109                 // <summary>
110                 //   The parent of this branching or null if this is the top-block.
111                 // </summary>
112                 public readonly FlowBranching Parent;
113
114                 // <summary>
115                 //   Start-Location of this flow branching.
116                 // </summary>
117                 public readonly Location Location;
118
119                 static int next_id = 0;
120                 int id;
121
122                 // <summary>
123                 //   The vector contains a BitArray with information about which local variables
124                 //   and parameters are already initialized at the current code position.
125                 // </summary>
126                 public class UsageVector {
127                         // <summary>
128                         //   The type of this branching.
129                         // </summary>
130                         public readonly SiblingType Type;
131
132                         // <summary>
133                         //   Start location of this branching.
134                         // </summary>
135                         public Location Location;
136
137                         // <summary>
138                         //   This is only valid for SwitchSection, Try, Catch and Finally.
139                         // </summary>
140                         public readonly Block Block;
141
142                         // <summary>
143                         //   The number of locals in this block.
144                         // </summary>
145                         public readonly int CountLocals;
146
147                         // <summary>
148                         //   If not null, then we inherit our state from this vector and do a
149                         //   copy-on-write.  If null, then we're the first sibling in a top-level
150                         //   block and inherit from the empty vector.
151                         // </summary>
152                         public readonly UsageVector InheritsFrom;
153
154                         // <summary>
155                         //   This is used to construct a list of UsageVector's.
156                         // </summary>
157                         public UsageVector Next;
158
159                         //
160                         // Private.
161                         //
162                         MyBitVector locals;
163                         bool is_unreachable;
164
165                         static int next_id = 0;
166                         int id;
167
168                         //
169                         // Normally, you should not use any of these constructors.
170                         //
171                         public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals)
172                         {
173                                 this.Type = type;
174                                 this.Block = block;
175                                 this.Location = loc;
176                                 this.InheritsFrom = parent;
177                                 this.CountLocals = num_locals;
178
179                                 locals = num_locals == 0 
180                                         ? MyBitVector.Empty
181                                         : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals);
182
183                                 if (parent != null)
184                                         is_unreachable = parent.is_unreachable;
185
186                                 id = ++next_id;
187
188                         }
189
190                         public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc)
191                                 : this (type, parent, block, loc, parent.CountLocals)
192                         { }
193
194                         private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc)
195                         {
196                                 this.Type = SiblingType.Block;
197                                 this.Location = loc;
198                                 this.Block = block;
199
200                                 this.is_unreachable = is_unreachable;
201
202                                 this.locals = locals;
203
204                                 id = ++next_id;
205
206                         }
207
208                         // <summary>
209                         //   This does a deep copy of the usage vector.
210                         // </summary>
211                         public UsageVector Clone ()
212                         {
213                                 UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals);
214
215                                 retval.locals = locals.Clone ();
216                                 retval.is_unreachable = is_unreachable;
217
218                                 return retval;
219                         }
220
221                         public bool IsAssigned (VariableInfo var, bool ignoreReachability)
222                         {
223                                 if (!ignoreReachability && !var.IsParameter && IsUnreachable)
224                                         return true;
225
226                                 return var.IsAssigned (locals);
227                         }
228
229                         public void SetAssigned (VariableInfo var)
230                         {
231                                 if (!var.IsParameter && IsUnreachable)
232                                         return;
233
234                                 var.SetAssigned (locals);
235                         }
236
237                         public bool IsFieldAssigned (VariableInfo var, string name)
238                         {
239                                 if (!var.IsParameter && IsUnreachable)
240                                         return true;
241
242                                 return var.IsFieldAssigned (locals, name);
243                         }
244
245                         public void SetFieldAssigned (VariableInfo var, string name)
246                         {
247                                 if (!var.IsParameter && IsUnreachable)
248                                         return;
249
250                                 var.SetFieldAssigned (locals, name);
251                         }
252
253                         public bool IsUnreachable {
254                                 get { return is_unreachable; }
255                         }
256
257                         public void ResetBarrier ()
258                         {
259                                 is_unreachable = false;
260                         }
261
262                         public void Goto ()
263                         {
264                                 is_unreachable = true;
265                         }
266
267                         public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc)
268                         {
269                                 if (sibling_list.Next == null)
270                                         return sibling_list;
271
272                                 MyBitVector locals = null;
273                                 bool is_unreachable = sibling_list.is_unreachable;
274
275                                 if (!sibling_list.IsUnreachable)
276                                         locals &= sibling_list.locals;
277
278                                 for (UsageVector child = sibling_list.Next; child != null; child = child.Next) {
279                                         is_unreachable &= child.is_unreachable;
280
281                                         if (!child.IsUnreachable)
282                                                 locals &= child.locals;
283                                 }
284
285                                 return new UsageVector (locals, is_unreachable, null, loc);
286                         }
287
288                         // <summary>
289                         //   Merges a child branching.
290                         // </summary>
291                         public UsageVector MergeChild (UsageVector child, bool overwrite)
292                         {
293                                 Report.Debug (2, "    MERGING CHILD EFFECTS", this, child, Type);
294
295                                 bool new_isunr = child.is_unreachable;
296
297                                 //
298                                 // We've now either reached the point after the branching or we will
299                                 // never get there since we always return or always throw an exception.
300                                 //
301                                 // If we can reach the point after the branching, mark all locals and
302                                 // parameters as initialized which have been initialized in all branches
303                                 // we need to look at (see above).
304                                 //
305
306                                 if ((Type == SiblingType.SwitchSection) && !new_isunr) {
307                                         Report.Error (163, Location,
308                                                       "Control cannot fall through from one " +
309                                                       "case label to another");
310                                         return child;
311                                 }
312
313                                 locals |= child.locals;
314
315                                 if (overwrite)
316                                         is_unreachable = new_isunr;
317                                 else
318                                         is_unreachable |= new_isunr;
319
320                                 return child;
321                         }
322
323                         public void MergeOrigins (UsageVector o_vectors)
324                         {
325                                 Report.Debug (1, "  MERGING BREAK ORIGINS", this);
326
327                                 if (o_vectors == null)
328                                         return;
329
330                                 if (IsUnreachable && locals != null)
331                                         locals.SetAll (true);
332
333                                 for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) {
334                                         Report.Debug (1, "    MERGING BREAK ORIGIN", vector);
335                                         if (vector.IsUnreachable)
336                                                 continue;
337                                         locals &= vector.locals;
338                                         is_unreachable &= vector.is_unreachable;
339                                 }
340
341                                 Report.Debug (1, "  MERGING BREAK ORIGINS DONE", this);
342                         }
343
344                         //
345                         // Debugging stuff.
346                         //
347
348                         public override string ToString ()
349                         {
350                                 return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals);
351                         }
352                 }
353
354                 // <summary>
355                 //   Creates a new flow branching which is contained in `parent'.
356                 //   You should only pass non-null for the `block' argument if this block
357                 //   introduces any new variables - in this case, we need to create a new
358                 //   usage vector with a different size than our parent's one.
359                 // </summary>
360                 protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype,
361                                          Block block, Location loc)
362                 {
363                         Parent = parent;
364                         Block = block;
365                         Location = loc;
366                         Type = type;
367                         id = ++next_id;
368
369                         UsageVector vector;
370                         if (Block != null) {
371                                 UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
372                                 vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots);
373                         } else {
374                                 vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc);
375                         }
376
377                         AddSibling (vector);
378                 }
379
380                 public abstract UsageVector CurrentUsageVector {
381                         get;
382                 }                               
383
384                 // <summary>
385                 //   Creates a sibling of the current usage vector.
386                 // </summary>
387                 public virtual void CreateSibling (Block block, SiblingType type)
388                 {
389                         UsageVector vector = new UsageVector (
390                                 type, Parent.CurrentUsageVector, block, Location);
391                         AddSibling (vector);
392
393                         Report.Debug (1, "  CREATED SIBLING", CurrentUsageVector);
394                 }
395
396                 public void CreateSibling ()
397                 {
398                         CreateSibling (null, SiblingType.Conditional);
399                 }
400
401                 protected abstract void AddSibling (UsageVector uv);
402
403                 protected abstract UsageVector Merge ();
404
405                 // <summary>
406                 //   Merge a child branching.
407                 // </summary>
408                 public UsageVector MergeChild (FlowBranching child)
409                 {
410                         bool overwrite = false;
411
412                         switch (child.Type) {
413                         case BranchingType.Labeled:
414                                 overwrite = true;
415                                 break;
416                         case BranchingType.Block:
417                                 if (child.Block != null && child.Block != child.Block.Explicit)
418                                         overwrite = true;
419                                 break;
420                         }
421
422                         Report.Debug (2, "  MERGING CHILD", this, child);
423                         UsageVector result = CurrentUsageVector.MergeChild (child.Merge (), overwrite);
424                         Report.Debug (2, "  MERGING CHILD DONE", this, result);
425                         return result;
426                 }
427
428                 public virtual bool InTryWithCatch ()
429                 {
430                         return Parent.InTryWithCatch ();
431                 }
432
433                 // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
434                 public virtual bool AddBreakOrigin (UsageVector vector, Location loc)
435                 {
436                         return Parent.AddBreakOrigin (vector, loc);
437                 }
438
439                 // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
440                 public virtual bool AddContinueOrigin (UsageVector vector, Location loc)
441                 {
442                         return Parent.AddContinueOrigin (vector, loc);
443                 }
444
445                 // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
446                 public virtual bool AddReturnOrigin (UsageVector vector, Location loc)
447                 {
448                         return Parent.AddReturnOrigin (vector, loc);
449                 }
450
451                 // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
452                 public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
453                 {
454                         return Parent.AddGotoOrigin (vector, goto_stmt);
455                 }
456
457                 public virtual void StealFinallyClauses (ref ArrayList list)
458                 {
459                         Parent.StealFinallyClauses (ref list);
460                 }
461
462                 public bool IsAssigned (VariableInfo vi)
463                 {
464                         return CurrentUsageVector.IsAssigned (vi, false);
465                 }
466
467                 public bool IsFieldAssigned (VariableInfo vi, string field_name)
468                 {
469                         return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name);
470                 }
471
472                 public void SetAssigned (VariableInfo vi)
473                 {
474                         CurrentUsageVector.SetAssigned (vi);
475                 }
476
477                 public void SetFieldAssigned (VariableInfo vi, string name)
478                 {
479                         CurrentUsageVector.SetFieldAssigned (vi, name);
480                 }
481
482                 public override string ToString ()
483                 {
484                         StringBuilder sb = new StringBuilder ();
485                         sb.Append (GetType ());
486                         sb.Append (" (");
487
488                         sb.Append (id);
489                         sb.Append (",");
490                         sb.Append (Type);
491                         if (Block != null) {
492                                 sb.Append (" - ");
493                                 sb.Append (Block.ID);
494                                 sb.Append (" - ");
495                                 sb.Append (Block.StartLocation);
496                         }
497                         sb.Append (" - ");
498                         // sb.Append (Siblings.Length);
499                         // sb.Append (" - ");
500                         sb.Append (CurrentUsageVector);
501                         sb.Append (")");
502                         return sb.ToString ();
503                 }
504
505                 public string Name {
506                         get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); }
507                 }
508         }
509
510         public class FlowBranchingBlock : FlowBranching
511         {
512                 UsageVector sibling_list = null;
513
514                 public FlowBranchingBlock (FlowBranching parent, BranchingType type,
515                                            SiblingType stype, Block block, Location loc)
516                         : base (parent, type, stype, block, loc)
517                 { }
518
519                 public override UsageVector CurrentUsageVector {
520                         get { return sibling_list; }
521                 }
522
523                 protected override void AddSibling (UsageVector sibling)
524                 {
525                         sibling.Next = sibling_list;
526                         sibling_list = sibling;
527                 }
528
529                 public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
530                 {
531                         LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target);
532                         if (stmt == null)
533                                 return Parent.AddGotoOrigin (vector, goto_stmt);
534
535                         // forward jump
536                         goto_stmt.SetResolvedTarget (stmt);
537                         stmt.AddUsageVector (vector);
538                         return false;
539                 }
540                 
541                 public static void Error_UnknownLabel (Location loc, string label)
542                 {
543                         Report.Error(159, loc, "The label `{0}:' could not be found within the scope of the goto statement",
544                                 label);
545                 }
546
547                 protected override UsageVector Merge ()
548                 {
549                         Report.Debug (2, "  MERGING SIBLINGS", Name);
550                         UsageVector vector = UsageVector.MergeSiblings (sibling_list, Location);
551                         Report.Debug (2, "  MERGING SIBLINGS DONE", Name, vector);
552                         return vector;
553                 }
554         }
555
556         public class FlowBranchingBreakable : FlowBranchingBlock
557         {
558                 UsageVector break_origins;
559
560                 public FlowBranchingBreakable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
561                         : base (parent, type, stype, block, loc)
562                 { }
563
564                 public override bool AddBreakOrigin (UsageVector vector, Location loc)
565                 {
566                         vector = vector.Clone ();
567                         vector.Next = break_origins;
568                         break_origins = vector;
569                         return false;
570                 }
571
572                 protected override UsageVector Merge ()
573                 {
574                         UsageVector vector = base.Merge ();
575                         vector.MergeOrigins (break_origins);
576                         return vector;
577                 }
578         }
579
580         public class FlowBranchingContinuable : FlowBranchingBlock
581         {
582                 UsageVector continue_origins;
583
584                 public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
585                         : base (parent, type, stype, block, loc)
586                 { }
587
588                 public override bool AddContinueOrigin (UsageVector vector, Location loc)
589                 {
590                         vector = vector.Clone ();
591                         vector.Next = continue_origins;
592                         continue_origins = vector;
593                         return false;
594                 }
595
596                 protected override UsageVector Merge ()
597                 {
598                         UsageVector vector = base.Merge ();
599                         vector.MergeOrigins (continue_origins);
600                         return vector;
601                 }
602         }
603
604         public class FlowBranchingLabeled : FlowBranchingBlock
605         {
606                 LabeledStatement stmt;
607                 UsageVector actual;
608
609                 public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt)
610                         : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc)
611                 {
612                         this.stmt = stmt;
613                         CurrentUsageVector.MergeOrigins (stmt.JumpOrigins);
614                         actual = CurrentUsageVector.Clone ();
615
616                         // stand-in for backward jumps
617                         CurrentUsageVector.ResetBarrier ();
618                 }
619
620                 public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
621                 {
622                         if (goto_stmt.Target != stmt.Name)
623                                 return Parent.AddGotoOrigin (vector, goto_stmt);
624
625                         // backward jump
626                         goto_stmt.SetResolvedTarget (stmt);
627                         actual.MergeOrigins (vector.Clone ());
628
629                         return false;
630                 }
631
632                 protected override UsageVector Merge ()
633                 {
634                         UsageVector vector = base.Merge ();
635
636                         if (actual.IsUnreachable)
637                                 Report.Warning (162, 2, stmt.loc, "Unreachable code detected");
638
639                         actual.MergeChild (vector, false);
640                         return actual;
641                 }
642         }
643
644         public class FlowBranchingToplevel : FlowBranchingBlock
645         {
646                 UsageVector return_origins;
647
648                 public FlowBranchingToplevel (FlowBranching parent, ToplevelBlock stmt)
649                         : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc)
650                 {
651                 }
652
653                 public override bool InTryWithCatch ()
654                 {
655                         return false;
656                 }
657
658                 public override bool AddBreakOrigin (UsageVector vector, Location loc)
659                 {
660                         Report.Error (139, loc, "No enclosing loop out of which to break or continue");
661                         return false;
662                 }
663
664                 public override bool AddContinueOrigin (UsageVector vector, Location loc)
665                 {
666                         Report.Error (139, loc, "No enclosing loop out of which to break or continue");
667                         return false;
668                 }
669
670                 public override bool AddReturnOrigin (UsageVector vector, Location loc)
671                 {
672                         vector = vector.Clone ();
673                         vector.Location = loc;
674                         vector.Next = return_origins;
675                         return_origins = vector;
676                         return false;
677                 }
678
679                 public override void StealFinallyClauses (ref ArrayList list)
680                 {
681                         // nothing to do
682                 }
683
684                 public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
685                 {
686                         string name = goto_stmt.Target;
687                         LabeledStatement s = Block.LookupLabel (name);
688                         if (s != null)
689                                 throw new InternalErrorException ("Shouldn't get here");
690
691                         if (Parent == null) {
692                                 Error_UnknownLabel (goto_stmt.loc, name);
693                                 return false;
694                         }
695
696                         int errors = Report.Errors;
697                         Parent.AddGotoOrigin (vector, goto_stmt);
698                         if (errors == Report.Errors)
699                                 Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method");
700                         return false;
701                 }
702
703                 protected override UsageVector Merge ()
704                 {
705                         for (UsageVector origin = return_origins; origin != null; origin = origin.Next)
706                                 Block.Toplevel.CheckOutParameters (origin, origin.Location);
707
708                         UsageVector vector = base.Merge ();
709                         Block.Toplevel.CheckOutParameters (vector, Block.loc);
710                         // Note: we _do_not_ merge in the return origins
711                         return vector;
712                 }
713
714                 public bool End ()
715                 {
716                         return Merge ().IsUnreachable;
717                 }
718         }
719
720         public class FlowBranchingException : FlowBranching
721         {
722                 ExceptionStatement stmt;
723                 UsageVector current_vector;
724                 UsageVector catch_vectors;
725                 UsageVector finally_vector;
726
727                 UsageVector break_origins;
728                 UsageVector continue_origins;
729                 UsageVector return_origins;
730                 GotoOrigin goto_origins;
731
732                 class GotoOrigin {
733                         public GotoOrigin Next;
734                         public Goto GotoStmt;
735                         public UsageVector Vector;
736
737                         public GotoOrigin (UsageVector vector, Goto goto_stmt, GotoOrigin next)
738                         {
739                                 Vector = vector;
740                                 GotoStmt = goto_stmt;
741                                 Next = next;
742                         }
743                 }
744
745                 bool emit_finally;
746
747                 public FlowBranchingException (FlowBranching parent,
748                                                ExceptionStatement stmt)
749                         : base (parent, BranchingType.Exception, SiblingType.Try,
750                                 null, stmt.loc)
751                 {
752                         this.stmt = stmt;
753                         this.emit_finally = true;
754                 }
755
756                 protected override void AddSibling (UsageVector sibling)
757                 {
758                         switch (sibling.Type) {
759                         case SiblingType.Try:
760                         case SiblingType.Catch:
761                                 sibling.Next = catch_vectors;
762                                 catch_vectors = sibling;
763                                 break;
764                         case SiblingType.Finally:
765                                 finally_vector = sibling;
766                                 break;
767                         default:
768                                 throw new InvalidOperationException ();
769                         }
770                         current_vector = sibling;
771                 }
772
773                 public override UsageVector CurrentUsageVector {
774                         get { return current_vector; }
775                 }
776
777                 public override bool InTryWithCatch ()
778                 {
779                         if (finally_vector == null) {
780                                 Try t = stmt as Try;
781                                 if (t != null && t.HasCatch)
782                                         return true;
783                         }
784
785                         return base.InTryWithCatch ();
786                 }
787
788                 public override bool AddBreakOrigin (UsageVector vector, Location loc)
789                 {
790                         vector = vector.Clone ();
791                         if (finally_vector != null) {
792                                 vector.MergeChild (finally_vector, false);
793                                 int errors = Report.Errors;
794                                 Parent.AddBreakOrigin (vector, loc);
795                                 if (errors == Report.Errors)
796                                         Report.Error (157, loc, "Control cannot leave the body of a finally clause");
797                         } else {
798                                 vector.Location = loc;
799                                 vector.Next = break_origins;
800                                 break_origins = vector;
801                         }
802                         return true;
803                 }
804
805                 public override bool AddContinueOrigin (UsageVector vector, Location loc)
806                 {
807                         vector = vector.Clone ();
808                         if (finally_vector != null) {
809                                 vector.MergeChild (finally_vector, false);
810                                 int errors = Report.Errors;
811                                 Parent.AddContinueOrigin (vector, loc);
812                                 if (errors == Report.Errors)
813                                         Report.Error (157, loc, "Control cannot leave the body of a finally clause");
814                         } else {
815                                 vector.Location = loc;
816                                 vector.Next = continue_origins;
817                                 continue_origins = vector;
818                         }
819                         return true;
820                 }
821
822                 public override bool AddReturnOrigin (UsageVector vector, Location loc)
823                 {
824                         vector = vector.Clone ();
825                         if (finally_vector != null) {
826                                 vector.MergeChild (finally_vector, false);
827                                 int errors = Report.Errors;
828                                 Parent.AddReturnOrigin (vector, loc);
829                                 if (errors == Report.Errors)
830                                         Report.Error (157, loc, "Control cannot leave the body of a finally clause");
831                         } else {
832                                 vector.Location = loc;
833                                 vector.Next = return_origins;
834                                 return_origins = vector;
835                         }
836                         return true;
837                 }
838
839                 public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
840                 {
841                         LabeledStatement s = current_vector.Block == null ? null : current_vector.Block.LookupLabel (goto_stmt.Target);
842                         if (s != null)
843                                 throw new InternalErrorException ("Shouldn't get here");
844
845                         vector = vector.Clone ();
846                         if (finally_vector != null) {
847                                 vector.MergeChild (finally_vector, false);
848                                 int errors = Report.Errors;
849                                 Parent.AddGotoOrigin (vector, goto_stmt);
850                                 if (errors == Report.Errors)
851                                         Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause");
852                         } else {
853                                 goto_origins = new GotoOrigin (vector, goto_stmt, goto_origins);
854                         }
855                         return true;
856                 }
857
858                 public override void StealFinallyClauses (ref ArrayList list)
859                 {
860                         if (list == null)
861                                 list = new ArrayList ();
862                         list.Add (stmt);
863                         emit_finally = false;
864                         base.StealFinallyClauses (ref list);
865                 }
866
867                 public bool EmitFinally {
868                         get { return emit_finally; }
869                 }
870
871                 protected override UsageVector Merge ()
872                 {
873                         Report.Debug (2, "  MERGING TRY/CATCH", Name);
874                         UsageVector vector = UsageVector.MergeSiblings (catch_vectors, Location);
875                         Report.Debug (2, "  MERGING TRY/CATCH DONE", vector);
876
877                         if (finally_vector != null)
878                                 vector.MergeChild (finally_vector, false);
879
880                         for (UsageVector origin = break_origins; origin != null; origin = origin.Next) {
881                                 if (finally_vector != null)
882                                         origin.MergeChild (finally_vector, false);
883                                 Parent.AddBreakOrigin (origin, origin.Location);
884                         }
885
886                         for (UsageVector origin = continue_origins; origin != null; origin = origin.Next) {
887                                 if (finally_vector != null)
888                                         origin.MergeChild (finally_vector, false);
889                                 Parent.AddContinueOrigin (origin, origin.Location);
890                         }
891
892                         for (UsageVector origin = return_origins; origin != null; origin = origin.Next) {
893                                 if (finally_vector != null)
894                                         origin.MergeChild (finally_vector, false);
895                                 Parent.AddReturnOrigin (origin, origin.Location);
896                         }
897
898                         for (GotoOrigin origin = goto_origins; origin != null; origin = origin.Next) {
899                                 if (finally_vector != null)
900                                         origin.Vector.MergeChild (finally_vector, false);
901                                 Parent.AddGotoOrigin (origin.Vector, origin.GotoStmt);
902                         }
903
904                         return vector;
905                 }
906         }
907
908         // <summary>
909         //   This is used by the flow analysis code to keep track of the type of local variables
910         //   and variables.
911         //
912         //   The flow code uses a BitVector to keep track of whether a variable has been assigned
913         //   or not.  This is easy for fundamental types (int, char etc.) or reference types since
914         //   you can only assign the whole variable as such.
915         //
916         //   For structs, we also need to keep track of all its fields.  To do this, we allocate one
917         //   bit for the struct itself (it's used if you assign/access the whole struct) followed by
918         //   one bit for each of its fields.
919         //
920         //   This class computes this `layout' for each type.
921         // </summary>
922         public class TypeInfo
923         {
924                 public readonly Type Type;
925
926                 // <summary>
927                 //   Total number of bits a variable of this type consumes in the flow vector.
928                 // </summary>
929                 public readonly int TotalLength;
930
931                 // <summary>
932                 //   Number of bits the simple fields of a variable of this type consume
933                 //   in the flow vector.
934                 // </summary>
935                 public readonly int Length;
936
937                 // <summary>
938                 //   This is only used by sub-structs.
939                 // </summary>
940                 public readonly int Offset;
941
942                 // <summary>
943                 //   If this is a struct.
944                 // </summary>
945                 public readonly bool IsStruct;       
946
947                 // <summary>
948                 //   If this is a struct, all fields which are structs theirselves.
949                 // </summary>
950                 public TypeInfo[] SubStructInfo;
951
952                 protected readonly StructInfo struct_info;
953                 private static Hashtable type_hash = new Hashtable ();
954
955                 public static TypeInfo GetTypeInfo (Type type)
956                 {
957                         TypeInfo info = (TypeInfo) type_hash [type];
958                         if (info != null)
959                                 return info;
960
961                         info = new TypeInfo (type);
962                         type_hash.Add (type, info);
963                         return info;
964                 }
965
966                 public static TypeInfo GetTypeInfo (TypeContainer tc)
967                 {
968                         TypeInfo info = (TypeInfo) type_hash [tc.TypeBuilder];
969                         if (info != null)
970                                 return info;
971
972                         info = new TypeInfo (tc);
973                         type_hash.Add (tc.TypeBuilder, info);
974                         return info;
975                 }
976
977                 private TypeInfo (Type type)
978                 {
979                         this.Type = type;
980
981                         struct_info = StructInfo.GetStructInfo (type);
982                         if (struct_info != null) {
983                                 Length = struct_info.Length;
984                                 TotalLength = struct_info.TotalLength;
985                                 SubStructInfo = struct_info.StructFields;
986                                 IsStruct = true;
987                         } else {
988                                 Length = 0;
989                                 TotalLength = 1;
990                                 IsStruct = false;
991                         }
992                 }
993
994                 private TypeInfo (TypeContainer tc)
995                 {
996                         this.Type = tc.TypeBuilder;
997
998                         struct_info = StructInfo.GetStructInfo (tc);
999                         if (struct_info != null) {
1000                                 Length = struct_info.Length;
1001                                 TotalLength = struct_info.TotalLength;
1002                                 SubStructInfo = struct_info.StructFields;
1003                                 IsStruct = true;
1004                         } else {
1005                                 Length = 0;
1006                                 TotalLength = 1;
1007                                 IsStruct = false;
1008                         }
1009                 }
1010
1011                 protected TypeInfo (StructInfo struct_info, int offset)
1012                 {
1013                         this.struct_info = struct_info;
1014                         this.Offset = offset;
1015                         this.Length = struct_info.Length;
1016                         this.TotalLength = struct_info.TotalLength;
1017                         this.SubStructInfo = struct_info.StructFields;
1018                         this.Type = struct_info.Type;
1019                         this.IsStruct = true;
1020                 }
1021
1022                 public int GetFieldIndex (string name)
1023                 {
1024                         if (struct_info == null)
1025                                 return 0;
1026
1027                         return struct_info [name];
1028                 }
1029
1030                 public TypeInfo GetSubStruct (string name)
1031                 {
1032                         if (struct_info == null)
1033                                 return null;
1034
1035                         return struct_info.GetStructField (name);
1036                 }
1037
1038                 // <summary>
1039                 //   A struct's constructor must always assign all fields.
1040                 //   This method checks whether it actually does so.
1041                 // </summary>
1042                 public bool IsFullyInitialized (FlowBranching branching, VariableInfo vi, Location loc)
1043                 {
1044                         if (struct_info == null)
1045                                 return true;
1046
1047                         bool ok = true;
1048                         for (int i = 0; i < struct_info.Count; i++) {
1049                                 FieldInfo field = struct_info.Fields [i];
1050
1051                                 if (!branching.IsFieldAssigned (vi, field.Name)) {
1052                                         Report.Error (171, loc,
1053                                                 "Field `{0}' must be fully assigned before control leaves the constructor",
1054                                                 TypeManager.GetFullNameSignature (field));
1055                                         ok = false;
1056                                 }
1057                         }
1058
1059                         return ok;
1060                 }
1061
1062                 public override string ToString ()
1063                 {
1064                         return String.Format ("TypeInfo ({0}:{1}:{2}:{3})",
1065                                               Type, Offset, Length, TotalLength);
1066                 }
1067
1068                 protected class StructInfo {
1069                         public readonly Type Type;
1070                         public readonly FieldInfo[] Fields;
1071                         public readonly TypeInfo[] StructFields;
1072                         public readonly int Count;
1073                         public readonly int CountPublic;
1074                         public readonly int CountNonPublic;
1075                         public readonly int Length;
1076                         public readonly int TotalLength;
1077                         public readonly bool HasStructFields;
1078
1079                         private static Hashtable field_type_hash = new Hashtable ();
1080                         private Hashtable struct_field_hash;
1081                         private Hashtable field_hash;
1082
1083                         protected bool InTransit = false;
1084
1085                         // Private constructor.  To save memory usage, we only need to create one instance
1086                         // of this class per struct type.
1087                         private StructInfo (Type type)
1088                         {
1089                                 this.Type = type;
1090
1091                                 field_type_hash.Add (type, this);
1092
1093                                 if (type is TypeBuilder) {
1094                                         TypeContainer tc = TypeManager.LookupTypeContainer (type);
1095
1096                                         ArrayList fields = null;
1097                                         if (tc != null)
1098                                                 fields = tc.Fields;
1099
1100                                         ArrayList public_fields = new ArrayList ();
1101                                         ArrayList non_public_fields = new ArrayList ();
1102
1103                                         if (fields != null) {
1104                                                 foreach (FieldBase field in fields) {
1105                                                         if ((field.ModFlags & Modifiers.STATIC) != 0)
1106                                                                 continue;
1107                                                         if ((field.ModFlags & Modifiers.PUBLIC) != 0)
1108                                                                 public_fields.Add (field.FieldBuilder);
1109                                                         else
1110                                                                 non_public_fields.Add (field.FieldBuilder);
1111                                                 }
1112                                         }
1113
1114                                         CountPublic = public_fields.Count;
1115                                         CountNonPublic = non_public_fields.Count;
1116                                         Count = CountPublic + CountNonPublic;
1117
1118                                         Fields = new FieldInfo [Count];
1119                                         public_fields.CopyTo (Fields, 0);
1120                                         non_public_fields.CopyTo (Fields, CountPublic);
1121 #if GMCS_SOURCE
1122                                 } else if (type is GenericTypeParameterBuilder) {
1123                                         CountPublic = CountNonPublic = Count = 0;
1124
1125                                         Fields = new FieldInfo [0];
1126 #endif
1127                                 } else {
1128                                         FieldInfo[] public_fields = type.GetFields (
1129                                                 BindingFlags.Instance|BindingFlags.Public);
1130                                         FieldInfo[] non_public_fields = type.GetFields (
1131                                                 BindingFlags.Instance|BindingFlags.NonPublic);
1132
1133                                         CountPublic = public_fields.Length;
1134                                         CountNonPublic = non_public_fields.Length;
1135                                         Count = CountPublic + CountNonPublic;
1136
1137                                         Fields = new FieldInfo [Count];
1138                                         public_fields.CopyTo (Fields, 0);
1139                                         non_public_fields.CopyTo (Fields, CountPublic);
1140                                 }
1141
1142                                 struct_field_hash = new Hashtable ();
1143                                 field_hash = new Hashtable ();
1144
1145                                 Length = 0;
1146                                 StructFields = new TypeInfo [Count];
1147                                 StructInfo[] sinfo = new StructInfo [Count];
1148
1149                                 InTransit = true;
1150
1151                                 for (int i = 0; i < Count; i++) {
1152                                         FieldInfo field = (FieldInfo) Fields [i];
1153
1154                                         sinfo [i] = GetStructInfo (field.FieldType);
1155                                         if (sinfo [i] == null)
1156                                                 field_hash.Add (field.Name, ++Length);
1157                                         else if (sinfo [i].InTransit) {
1158                                                 Report.Error (523, String.Format (
1159                                                                       "Struct member `{0}.{1}' of type `{2}' causes " +
1160                                                                       "a cycle in the structure layout",
1161                                                                       type, field.Name, sinfo [i].Type));
1162                                                 sinfo [i] = null;
1163                                                 return;
1164                                         }
1165                                 }
1166
1167                                 InTransit = false;
1168
1169                                 TotalLength = Length + 1;
1170                                 for (int i = 0; i < Count; i++) {
1171                                         FieldInfo field = (FieldInfo) Fields [i];
1172
1173                                         if (sinfo [i] == null)
1174                                                 continue;
1175
1176                                         field_hash.Add (field.Name, TotalLength);
1177
1178                                         HasStructFields = true;
1179                                         StructFields [i] = new TypeInfo (sinfo [i], TotalLength);
1180                                         struct_field_hash.Add (field.Name, StructFields [i]);
1181                                         TotalLength += sinfo [i].TotalLength;
1182                                 }
1183                         }
1184
1185                         public int this [string name] {
1186                                 get {
1187                                         if (field_hash.Contains (name))
1188                                                 return (int) field_hash [name];
1189                                         else
1190                                                 return 0;
1191                                 }
1192                         }
1193
1194                         public TypeInfo GetStructField (string name)
1195                         {
1196                                 return (TypeInfo) struct_field_hash [name];
1197                         }
1198
1199                         public static StructInfo GetStructInfo (Type type)
1200                         {
1201                                 if (!TypeManager.IsValueType (type) || TypeManager.IsEnumType (type) ||
1202                                     TypeManager.IsBuiltinType (type))
1203                                         return null;
1204
1205                                 StructInfo info = (StructInfo) field_type_hash [type];
1206                                 if (info != null)
1207                                         return info;
1208
1209                                 return new StructInfo (type);
1210                         }
1211
1212                         public static StructInfo GetStructInfo (TypeContainer tc)
1213                         {
1214                                 StructInfo info = (StructInfo) field_type_hash [tc.TypeBuilder];
1215                                 if (info != null)
1216                                         return info;
1217
1218                                 return new StructInfo (tc.TypeBuilder);
1219                         }
1220                 }
1221         }
1222
1223         // <summary>
1224         //   This is used by the flow analysis code to store information about a single local variable
1225         //   or parameter.  Depending on the variable's type, we need to allocate one or more elements
1226         //   in the BitVector - if it's a fundamental or reference type, we just need to know whether
1227         //   it has been assigned or not, but for structs, we need this information for each of its fields.
1228         // </summary>
1229         public class VariableInfo {
1230                 public readonly string Name;
1231                 public readonly TypeInfo TypeInfo;
1232
1233                 // <summary>
1234                 //   The bit offset of this variable in the flow vector.
1235                 // </summary>
1236                 public readonly int Offset;
1237
1238                 // <summary>
1239                 //   The number of bits this variable needs in the flow vector.
1240                 //   The first bit always specifies whether the variable as such has been assigned while
1241                 //   the remaining bits contain this information for each of a struct's fields.
1242                 // </summary>
1243                 public readonly int Length;
1244
1245                 // <summary>
1246                 //   If this is a parameter of local variable.
1247                 // </summary>
1248                 public readonly bool IsParameter;
1249
1250                 public readonly LocalInfo LocalInfo;
1251
1252                 readonly VariableInfo Parent;
1253                 VariableInfo[] sub_info;
1254
1255                 protected VariableInfo (string name, Type type, int offset)
1256                 {
1257                         this.Name = name;
1258                         this.Offset = offset;
1259                         this.TypeInfo = TypeInfo.GetTypeInfo (type);
1260
1261                         Length = TypeInfo.TotalLength;
1262
1263                         Initialize ();
1264                 }
1265
1266                 protected VariableInfo (VariableInfo parent, TypeInfo type)
1267                 {
1268                         this.Name = parent.Name;
1269                         this.TypeInfo = type;
1270                         this.Offset = parent.Offset + type.Offset;
1271                         this.Parent = parent;
1272                         this.Length = type.TotalLength;
1273
1274                         this.IsParameter = parent.IsParameter;
1275                         this.LocalInfo = parent.LocalInfo;
1276
1277                         Initialize ();
1278                 }
1279
1280                 protected void Initialize ()
1281                 {
1282                         TypeInfo[] sub_fields = TypeInfo.SubStructInfo;
1283                         if (sub_fields != null) {
1284                                 sub_info = new VariableInfo [sub_fields.Length];
1285                                 for (int i = 0; i < sub_fields.Length; i++) {
1286                                         if (sub_fields [i] != null)
1287                                                 sub_info [i] = new VariableInfo (this, sub_fields [i]);
1288                                 }
1289                         } else
1290                                 sub_info = new VariableInfo [0];
1291                 }
1292
1293                 public VariableInfo (LocalInfo local_info, int offset)
1294                         : this (local_info.Name, local_info.VariableType, offset)
1295                 {
1296                         this.LocalInfo = local_info;
1297                         this.IsParameter = false;
1298                 }
1299
1300                 public VariableInfo (Parameters ip, int i, int offset)
1301                         : this (ip.ParameterName (i), TypeManager.GetElementType (ip.ParameterType (i)), offset)
1302                 {
1303                         this.IsParameter = true;
1304                 }
1305
1306                 public bool IsAssigned (EmitContext ec)
1307                 {
1308                         return !ec.DoFlowAnalysis ||
1309                                 ec.OmitStructFlowAnalysis && TypeInfo.IsStruct ||
1310                                 ec.CurrentBranching.IsAssigned (this);
1311                 }
1312
1313                 public bool IsAssigned (EmitContext ec, Location loc)
1314                 {
1315                         if (IsAssigned (ec))
1316                                 return true;
1317
1318                         Report.Error (165, loc,
1319                                       "Use of unassigned local variable `" + Name + "'");
1320                         ec.CurrentBranching.SetAssigned (this);
1321                         return false;
1322                 }
1323
1324                 public bool IsAssigned (MyBitVector vector)
1325                 {
1326                         if (vector == null)
1327                                 return true;
1328
1329                         if (vector [Offset])
1330                                 return true;
1331
1332                         // FIXME: Fix SetFieldAssigned to set the whole range like SetAssigned below. Then, get rid of this stanza
1333                         for (VariableInfo parent = Parent; parent != null; parent = parent.Parent) {
1334                                 if (vector [parent.Offset]) {
1335                                         // 'parent' is assigned, but someone forgot to note that all its components are assigned too
1336                                         parent.SetAssigned (vector);
1337                                         return true;
1338                                 }
1339                         }
1340
1341                         // Return unless this is a struct.
1342                         if (!TypeInfo.IsStruct)
1343                                 return false;
1344
1345                         // Ok, so each field must be assigned.
1346                         for (int i = 0; i < TypeInfo.Length; i++) {
1347                                 if (!vector [Offset + i + 1])
1348                                         return false;
1349                         }
1350
1351                         // Ok, now check all fields which are structs.
1352                         for (int i = 0; i < sub_info.Length; i++) {
1353                                 VariableInfo sinfo = sub_info [i];
1354                                 if (sinfo == null)
1355                                         continue;
1356
1357                                 if (!sinfo.IsAssigned (vector))
1358                                         return false;
1359                         }
1360
1361                         vector [Offset] = true;
1362                         return true;
1363                 }
1364
1365                 public void SetAssigned (EmitContext ec)
1366                 {
1367                         if (ec.DoFlowAnalysis)
1368                                 ec.CurrentBranching.SetAssigned (this);
1369                 }
1370
1371                 public void SetAssigned (MyBitVector vector)
1372                 {
1373                         if (Length == 1)
1374                                 vector [Offset] = true;
1375                         else
1376                                 vector.SetRange (Offset, Length);
1377                 }
1378
1379                 public bool IsFieldAssigned (EmitContext ec, string name, Location loc)
1380                 {
1381                         if (!ec.DoFlowAnalysis ||
1382                                 ec.OmitStructFlowAnalysis && TypeInfo.IsStruct ||
1383                                 ec.CurrentBranching.IsFieldAssigned (this, name))
1384                                 return true;
1385
1386                         Report.Error (170, loc,
1387                                       "Use of possibly unassigned field `" + name + "'");
1388                         ec.CurrentBranching.SetFieldAssigned (this, name);
1389                         return false;
1390                 }
1391
1392                 public bool IsFieldAssigned (MyBitVector vector, string field_name)
1393                 {
1394                         int field_idx = TypeInfo.GetFieldIndex (field_name);
1395
1396                         if (field_idx == 0)
1397                                 return true;
1398
1399                         return vector [Offset + field_idx];
1400                 }
1401
1402                 public void SetFieldAssigned (EmitContext ec, string name)
1403                 {
1404                         if (ec.DoFlowAnalysis)
1405                                 ec.CurrentBranching.SetFieldAssigned (this, name);
1406                 }
1407
1408                 public void SetFieldAssigned (MyBitVector vector, string field_name)
1409                 {
1410                         int field_idx = TypeInfo.GetFieldIndex (field_name);
1411
1412                         if (field_idx == 0)
1413                                 return;
1414
1415                         vector [Offset + field_idx] = true;
1416                 }
1417
1418                 public VariableInfo GetSubStruct (string name)
1419                 {
1420                         TypeInfo type = TypeInfo.GetSubStruct (name);
1421
1422                         if (type == null)
1423                                 return null;
1424
1425                         return new VariableInfo (this, type);
1426                 }
1427
1428                 public override string ToString ()
1429                 {
1430                         return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})",
1431                                               Name, TypeInfo, Offset, Length, IsParameter);
1432                 }
1433         }
1434
1435         // <summary>
1436         //   This is a special bit vector which can inherit from another bit vector doing a
1437         //   copy-on-write strategy.  The inherited vector may have a smaller size than the
1438         //   current one.
1439         // </summary>
1440         public class MyBitVector {
1441                 public readonly int Count;
1442                 public static readonly MyBitVector Empty = new MyBitVector ();
1443
1444                 // Invariant: vector != null => vector.Count == Count
1445                 // Invariant: vector == null || shared == null
1446                 //            i.e., at most one of 'vector' and 'shared' can be non-null.  They can both be null -- that means all-ones
1447                 // The object in 'shared' cannot be modified, while 'vector' can be freely modified
1448                 BitArray vector, shared;
1449
1450                 MyBitVector ()
1451                 {
1452                         shared = new BitArray (0, false);
1453                 }
1454
1455                 public MyBitVector (MyBitVector InheritsFrom, int Count)
1456                 {
1457                         if (InheritsFrom != null)
1458                                 shared = InheritsFrom.Shared;
1459
1460                         this.Count = Count;
1461                 }
1462
1463                 // Use this accessor to get a shareable copy of the underlying BitArray representation
1464                 BitArray Shared {
1465                         get {
1466                                 // Post-condition: vector == null
1467                                 if (shared == null) {
1468                                         shared = vector;
1469                                         vector = null;
1470                                 }
1471                                 return shared;
1472                         }
1473                 }
1474
1475                 // <summary>
1476                 //   Get/set bit `index' in the bit vector.
1477                 // </summary>
1478                 public bool this [int index] {
1479                         get {
1480                                 if (index >= Count)
1481                                         throw new ArgumentOutOfRangeException ();
1482
1483                                 if (vector != null)
1484                                         return vector [index];
1485                                 if (shared == null)
1486                                         return true;
1487                                 if (index < shared.Count)
1488                                         return shared [index];
1489                                 return false;
1490                         }
1491
1492                         set {
1493                                 // Only copy the vector if we're actually modifying it.
1494                                 if (this [index] != value) {
1495                                         if (vector == null)
1496                                                 initialize_vector ();
1497                                         vector [index] = value;
1498                                 }
1499                         }
1500                 }
1501
1502                 // <summary>
1503                 //   Performs an `or' operation on the bit vector.  The `new_vector' may have a
1504                 //   different size than the current one.
1505                 // </summary>
1506                 private MyBitVector Or (MyBitVector new_vector)
1507                 {
1508                         if (Count == 0 || new_vector.Count == 0)
1509                                 return this;
1510
1511                         BitArray o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
1512
1513                         if (o == null) {
1514                                 int n = new_vector.Count;
1515                                 if (n < Count) {
1516                                         for (int i = 0; i < n; ++i)
1517                                                 this [i] = true;
1518                                 } else {
1519                                         SetAll (true);
1520                                 }
1521                                 return this;
1522                         }
1523
1524                         if (Count == o.Count) {
1525                                 if (vector == null) {
1526                                         if (shared == null)
1527                                                 return this;
1528                                         initialize_vector ();
1529                                 }
1530                                 vector.Or (o);
1531                                 return this;
1532                         }
1533
1534                         int min = o.Count;
1535                         if (Count < min)
1536                                 min = Count;
1537
1538                         for (int i = 0; i < min; i++) {
1539                                 if (o [i])
1540                                         this [i] = true;
1541                         }
1542
1543                         return this;
1544                 }
1545
1546                 // <summary>
1547                 //   Performs an `and' operation on the bit vector.  The `new_vector' may have
1548                 //   a different size than the current one.
1549                 // </summary>
1550                 private MyBitVector And (MyBitVector new_vector)
1551                 {
1552                         if (Count == 0)
1553                                 return this;
1554
1555                         BitArray o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
1556
1557                         if (o == null) {
1558                                 for (int i = new_vector.Count; i < Count; ++i)
1559                                         this [i] = false;
1560                                 return this;
1561                         }
1562
1563                         if (o.Count == 0) {
1564                                 SetAll (false);
1565                                 return this;
1566                         }
1567
1568                         if (Count == o.Count) {
1569                                 if (vector == null) {
1570                                         if (shared == null) {
1571                                                 shared = new_vector.Shared;
1572                                                 return this;
1573                                         }
1574                                         initialize_vector ();
1575                                 }
1576                                 vector.And (o);
1577                                 return this;
1578                         }
1579
1580                         int min = o.Count;
1581                         if (Count < min)
1582                                 min = Count;
1583
1584                         for (int i = 0; i < min; i++) {
1585                                 if (! o [i])
1586                                         this [i] = false;
1587                         }
1588
1589                         for (int i = min; i < Count; i++)
1590                                 this [i] = false;
1591
1592                         return this;
1593                 }
1594
1595                 public static MyBitVector operator & (MyBitVector a, MyBitVector b)
1596                 {
1597                         if (a == b)
1598                                 return a;
1599                         if (a == null)
1600                                 return b.Clone ();
1601                         if (b == null)
1602                                 return a.Clone ();
1603                         if (a.Count > b.Count)
1604                                 return a.Clone ().And (b);
1605                         else
1606                                 return b.Clone ().And (a);                                      
1607                 }
1608
1609                 public static MyBitVector operator | (MyBitVector a, MyBitVector b)
1610                 {
1611                         if (a == b)
1612                                 return a;
1613                         if (a == null)
1614                                 return new MyBitVector (null, b.Count);
1615                         if (b == null)
1616                                 return new MyBitVector (null, a.Count);
1617                         if (a.Count > b.Count)
1618                                 return a.Clone ().Or (b);
1619                         else
1620                                 return b.Clone ().Or (a);
1621                 }
1622
1623                 public MyBitVector Clone ()
1624                 {
1625                         return Count == 0 ? Empty : new MyBitVector (this, Count);
1626                 }
1627
1628                 public void SetRange (int offset, int length)
1629                 {
1630                         if (offset > Count || offset + length > Count)
1631                                 throw new ArgumentOutOfRangeException ();
1632
1633                         if (shared == null && vector == null)
1634                                 return;
1635
1636                         int i = 0;
1637                         if (shared != null) {
1638                                 if (offset + length <= shared.Count) {
1639                                         for (; i < length; ++i)
1640                                                 if (!shared [i+offset])
1641                                                     break;
1642                                         if (i == length)
1643                                                 return;
1644                                 }
1645                                 initialize_vector ();
1646                         }
1647                         for (; i < length; ++i)
1648                                 vector [i+offset] = true;
1649
1650                 }
1651
1652                 public void SetAll (bool value)
1653                 {
1654                         // Don't clobber Empty
1655                         if (Count == 0)
1656                                 return;
1657                         shared = value ? null : Empty.Shared;
1658                         vector = null;
1659                 }
1660
1661                 void initialize_vector ()
1662                 {
1663                         // Post-condition: vector != null
1664                         if (shared == null) {
1665                                 vector = new BitArray (Count, true);
1666                                 return;
1667                         }
1668
1669                         vector = new BitArray (shared);
1670                         if (Count != vector.Count)
1671                                 vector.Length = Count;
1672                         shared = null;
1673                 }
1674
1675                 StringBuilder Dump (StringBuilder sb)
1676                 {
1677                         BitArray dump = vector == null ? shared : vector;
1678                         if (dump == null)
1679                                 return sb.Append ("/");
1680                         if (dump == shared)
1681                                 sb.Append ("=");
1682                         for (int i = 0; i < dump.Count; i++)
1683                                 sb.Append (dump [i] ? "1" : "0");
1684                         return sb;
1685                 }
1686
1687                 public override string ToString ()
1688                 {
1689                         return Dump (new StringBuilder ("{")).Append ("}").ToString ();
1690                 }
1691         }
1692 }