X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fflowanalysis.cs;h=2213d36e59eacb468a4ba34648963c64140dc6bc;hb=3c28dc153645532e837e42ecbd8979d05dc944a8;hp=5659f117df1c39cb1c1b307007041f1686468e7b;hpb=cc7525c98bd49cf154c92a4aa41571ecf0b52b2b;p=mono.git diff --git a/mcs/mcs/flowanalysis.cs b/mcs/mcs/flowanalysis.cs index 5659f117df1..2213d36e59e 100644 --- a/mcs/mcs/flowanalysis.cs +++ b/mcs/mcs/flowanalysis.cs @@ -5,7 +5,8 @@ // Martin Baulig (martin@ximian.com) // Raja R Harinath (rharinath@novell.com) // -// (C) 2001, 2002, 2003 Ximian, Inc. +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. // using System; @@ -42,17 +43,20 @@ namespace Mono.CSharp // part of a block headed by a jump target Labeled, - // Try/Catch block. + // TryCatch block. + TryCatch, + + // TryFinally, Using, Lock, CollectionForeach Exception, // Switch block. Switch, - // Switch section. - SwitchSection, - // The toplevel block of a function - Toplevel + Toplevel, + + // An iterator block + Iterator } // @@ -73,14 +77,12 @@ namespace Mono.CSharp 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.SwitchSection: - return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc); - case BranchingType.Block: return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc); @@ -116,8 +118,6 @@ namespace Mono.CSharp // public readonly Location Location; - protected VariableMap param_map; - static int next_id = 0; int id; @@ -141,11 +141,6 @@ namespace Mono.CSharp // public readonly Block Block; - // - // The number of parameters in this block. - // - public readonly int CountParameters; - // // The number of locals in this block. // @@ -166,7 +161,7 @@ namespace Mono.CSharp // // Private. // - MyBitVector locals, parameters; + MyBitVector locals; bool is_unreachable; static int next_id = 0; @@ -175,23 +170,18 @@ namespace Mono.CSharp // // Normally, you should not use any of these constructors. // - public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_params, int num_locals) + public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals) { this.Type = type; this.Block = block; this.Location = loc; this.InheritsFrom = parent; - this.CountParameters = num_params; this.CountLocals = num_locals; locals = num_locals == 0 ? MyBitVector.Empty : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals); - parameters = num_params == 0 - ? MyBitVector.Empty - : new MyBitVector (parent == null ? MyBitVector.Empty : parent.parameters, num_params); - if (parent != null) is_unreachable = parent.is_unreachable; @@ -200,10 +190,10 @@ namespace Mono.CSharp } public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc) - : this (type, parent, block, loc, parent.CountParameters, parent.CountLocals) + : this (type, parent, block, loc, parent.CountLocals) { } - private UsageVector (MyBitVector parameters, MyBitVector locals, bool is_unreachable, Block block, Location loc) + private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc) { this.Type = SiblingType.Block; this.Location = loc; @@ -211,7 +201,6 @@ namespace Mono.CSharp this.is_unreachable = is_unreachable; - this.parameters = parameters; this.locals = locals; id = ++next_id; @@ -223,10 +212,9 @@ namespace Mono.CSharp // public UsageVector Clone () { - UsageVector retval = new UsageVector (Type, null, Block, Location, CountParameters, CountLocals); + UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals); retval.locals = locals.Clone (); - retval.parameters = parameters.Clone (); retval.is_unreachable = is_unreachable; return retval; @@ -237,7 +225,7 @@ namespace Mono.CSharp if (!ignoreReachability && !var.IsParameter && IsUnreachable) return true; - return var.IsAssigned (var.IsParameter ? parameters : locals); + return var.IsAssigned (locals); } public void SetAssigned (VariableInfo var) @@ -245,7 +233,7 @@ namespace Mono.CSharp if (!var.IsParameter && IsUnreachable) return; - var.SetAssigned (var.IsParameter ? parameters : locals); + var.SetAssigned (locals); } public bool IsFieldAssigned (VariableInfo var, string name) @@ -253,7 +241,7 @@ namespace Mono.CSharp if (!var.IsParameter && IsUnreachable) return true; - return var.IsFieldAssigned (var.IsParameter ? parameters : locals, name); + return var.IsFieldAssigned (locals, name); } public void SetFieldAssigned (VariableInfo var, string name) @@ -261,7 +249,7 @@ namespace Mono.CSharp if (!var.IsParameter && IsUnreachable) return; - var.SetFieldAssigned (var.IsParameter ? parameters : locals, name); + var.SetFieldAssigned (locals, name); } public bool IsUnreachable { @@ -284,24 +272,19 @@ namespace Mono.CSharp return sibling_list; MyBitVector locals = null; - MyBitVector parameters = null; bool is_unreachable = sibling_list.is_unreachable; - if (!sibling_list.IsUnreachable) { + if (!sibling_list.IsUnreachable) locals &= sibling_list.locals; - parameters &= sibling_list.parameters; - } for (UsageVector child = sibling_list.Next; child != null; child = child.Next) { is_unreachable &= child.is_unreachable; - if (!child.IsUnreachable) { + if (!child.IsUnreachable) locals &= child.locals; - parameters &= child.parameters; - } } - return new UsageVector (parameters, locals, is_unreachable, null, loc); + return new UsageVector (locals, is_unreachable, null, loc); } // @@ -330,7 +313,10 @@ namespace Mono.CSharp } locals |= child.locals; - parameters |= child.parameters; + + // throw away un-necessary information about variables in child blocks + if (locals.Count != CountLocals) + locals = new MyBitVector (locals, CountLocals); if (overwrite) is_unreachable = new_isunr; @@ -347,19 +333,14 @@ namespace Mono.CSharp if (o_vectors == null) return; - if (IsUnreachable) { - if (locals != null) - locals.SetAll (true); - if (parameters != null) - parameters.SetAll (true); - } + if (IsUnreachable && locals != null) + locals.SetAll (true); for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) { Report.Debug (1, " MERGING BREAK ORIGIN", vector); if (vector.IsUnreachable) continue; locals &= vector.locals; - parameters &= vector.parameters; is_unreachable &= vector.is_unreachable; } @@ -372,7 +353,7 @@ namespace Mono.CSharp public override string ToString () { - return String.Format ("Vector ({0},{1},{2}-{3}-{4})", Type, id, is_unreachable, parameters, locals); + return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals); } } @@ -393,14 +374,10 @@ namespace Mono.CSharp UsageVector vector; if (Block != null) { - param_map = Block.ParameterMap; UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null; - vector = new UsageVector ( - stype, parent_vector, Block, loc, param_map.Length, Block.AssignableSlots); + vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots); } else { - param_map = Parent.param_map; - vector = new UsageVector ( - stype, Parent.CurrentUsageVector, null, loc); + vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc); } AddSibling (vector); @@ -431,22 +408,19 @@ namespace Mono.CSharp protected abstract UsageVector Merge (); - // - // Merge a child branching. - // public UsageVector MergeChild (FlowBranching child) { - bool overwrite = child.Type == BranchingType.Labeled || - (child.Type == BranchingType.Block && child.Block != null && child.Block.Implicit); - Report.Debug (2, " MERGING CHILD", this, child); - UsageVector result = CurrentUsageVector.MergeChild (child.Merge (), overwrite); - Report.Debug (2, " MERGING CHILD DONE", this, result); - return result; + return CurrentUsageVector.MergeChild (child.Merge (), true); } - public virtual bool InTryWithCatch () + public virtual bool CheckRethrow (Location loc) { - return Parent.InTryWithCatch (); + return Parent.CheckRethrow (loc); + } + + public virtual bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + return Parent.AddResumePoint (stmt, loc, out pc); } // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) @@ -462,9 +436,9 @@ namespace Mono.CSharp } // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) - public virtual bool AddReturnOrigin (UsageVector vector, Location loc) + public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) { - return Parent.AddReturnOrigin (vector, loc); + return Parent.AddReturnOrigin (vector, stmt); } // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) @@ -473,11 +447,6 @@ namespace Mono.CSharp return Parent.AddGotoOrigin (vector, goto_stmt); } - public virtual void StealFinallyClauses (ref ArrayList list) - { - Parent.StealFinallyClauses (ref list); - } - public bool IsAssigned (VariableInfo vi) { return CurrentUsageVector.IsAssigned (vi, false); @@ -541,6 +510,8 @@ namespace Mono.CSharp protected override void AddSibling (UsageVector sibling) { + if (sibling_list != null && sibling_list.Type == SiblingType.Block) + throw new InternalErrorException ("Blocks don't have sibling flow paths"); sibling.Next = sibling_list; sibling_list = sibling; } @@ -660,6 +631,22 @@ namespace Mono.CSharp } } + public class FlowBranchingIterator : FlowBranchingBlock + { + Iterator iterator; + public FlowBranchingIterator (FlowBranching parent, Iterator iterator) + : base (parent, BranchingType.Iterator, SiblingType.Block, null, iterator.Location) + { + this.iterator = iterator; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + pc = iterator.AddResumePoint (stmt); + return false; + } + } + public class FlowBranchingToplevel : FlowBranchingBlock { UsageVector return_origins; @@ -669,30 +656,15 @@ namespace Mono.CSharp { } - // - // Check whether all `out' parameters have been assigned. - // - void CheckOutParameters (UsageVector vector, Location loc) + public override bool CheckRethrow (Location loc) { - if (vector.IsUnreachable) - return; - for (int i = 0; i < param_map.Count; i++) { - VariableInfo var = param_map [i]; - - if (var == null) - continue; - - if (vector.IsAssigned (var, false)) - continue; - - Report.Error (177, loc, "The out parameter `{0}' must be assigned to before control leaves the current method", - var.Name); - } + Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause"); + return false; } - public override bool InTryWithCatch () + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) { - return false; + throw new InternalErrorException ("A yield in a non-iterator block"); } public override bool AddBreakOrigin (UsageVector vector, Location loc) @@ -707,20 +679,15 @@ namespace Mono.CSharp return false; } - public override bool AddReturnOrigin (UsageVector vector, Location loc) + public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) { vector = vector.Clone (); - vector.Location = loc; + vector.Location = stmt.loc; vector.Next = return_origins; return_origins = vector; return false; } - public override void StealFinallyClauses (ref ArrayList list) - { - // nothing to do - } - public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { string name = goto_stmt.Target; @@ -743,10 +710,10 @@ namespace Mono.CSharp protected override UsageVector Merge () { for (UsageVector origin = return_origins; origin != null; origin = origin.Next) - CheckOutParameters (origin, origin.Location); + Block.Toplevel.CheckOutParameters (origin, origin.Location); UsageVector vector = base.Merge (); - CheckOutParameters (vector, Block.loc); + Block.Toplevel.CheckOutParameters (vector, Block.loc); // Note: we _do_not_ merge in the return origins return vector; } @@ -757,32 +724,146 @@ namespace Mono.CSharp } } + public class FlowBranchingTryCatch : FlowBranchingBlock + { + TryCatch stmt; + public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt) + : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc) + { + this.stmt = stmt; + } + + public override bool CheckRethrow (Location loc) + { + return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc); + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + int errors = Report.Errors; + Parent.AddResumePoint (stmt, loc, out pc); + if (errors == Report.Errors) { + if (CurrentUsageVector.Next == null) + Report.Error (1626, loc, "Cannot yield a value in the body of a try block with a catch clause"); + else + Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause"); + } + return true; + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + Parent.AddBreakOrigin (vector, loc); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + Parent.AddContinueOrigin (vector, loc); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) + { + Parent.AddReturnOrigin (vector, exit_stmt); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + Parent.AddGotoOrigin (vector, goto_stmt); + return true; + } + } + public class FlowBranchingException : FlowBranching { ExceptionStatement stmt; UsageVector current_vector; - UsageVector catch_vectors; + UsageVector try_vector; UsageVector finally_vector; - UsageVector break_origins; - UsageVector continue_origins; - UsageVector return_origins; - GotoOrigin goto_origins; - - class GotoOrigin { - public GotoOrigin Next; - public Goto GotoStmt; - public UsageVector Vector; + abstract class SavedOrigin { + public readonly SavedOrigin Next; + public readonly UsageVector Vector; - public GotoOrigin (UsageVector vector, Goto goto_stmt, GotoOrigin next) + protected SavedOrigin (SavedOrigin next, UsageVector vector) { - Vector = vector; - GotoStmt = goto_stmt; Next = next; + Vector = vector.Clone (); + } + + protected abstract void DoPropagateFinally (FlowBranching parent); + public void PropagateFinally (UsageVector finally_vector, FlowBranching parent) + { + if (finally_vector != null) + Vector.MergeChild (finally_vector, false); + DoPropagateFinally (parent); + } + } + + class BreakOrigin : SavedOrigin { + Location Loc; + public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc) + : base (next, vector) + { + Loc = loc; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddBreakOrigin (Vector, Loc); + } + } + + class ContinueOrigin : SavedOrigin { + Location Loc; + public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc) + : base (next, vector) + { + Loc = loc; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddContinueOrigin (Vector, Loc); + } + } + + class ReturnOrigin : SavedOrigin { + public ExitStatement Stmt; + + public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt) + : base (next, vector) + { + Stmt = stmt; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddReturnOrigin (Vector, Stmt); } } - bool emit_finally; + class GotoOrigin : SavedOrigin { + public Goto Stmt; + + public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt) + : base (next, vector) + { + Stmt = stmt; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddGotoOrigin (Vector, Stmt); + } + } + + SavedOrigin saved_origins; public FlowBranchingException (FlowBranching parent, ExceptionStatement stmt) @@ -790,16 +871,13 @@ namespace Mono.CSharp null, stmt.loc) { this.stmt = stmt; - this.emit_finally = true; } protected override void AddSibling (UsageVector sibling) { switch (sibling.Type) { case SiblingType.Try: - case SiblingType.Catch: - sibling.Next = catch_vectors; - catch_vectors = sibling; + try_vector = sibling; break; case SiblingType.Finally: finally_vector = sibling; @@ -814,65 +892,74 @@ namespace Mono.CSharp get { return current_vector; } } - public override bool InTryWithCatch () + public override bool CheckRethrow (Location loc) { - if (finally_vector == null) { - Try t = stmt as Try; - if (t != null && t.HasCatch) - return true; - } + if (!Parent.CheckRethrow (loc)) + return false; + if (finally_vector == null) + return true; + Report.Error (724, loc, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause"); + return false; + } - return base.InTryWithCatch (); + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + int errors = Report.Errors; + Parent.AddResumePoint (this.stmt, loc, out pc); + if (errors == Report.Errors) { + if (finally_vector == null) + this.stmt.AddResumePoint (stmt, pc); + else + Report.Error (1625, loc, "Cannot yield in the body of a finally clause"); + } + return true; } public override bool AddBreakOrigin (UsageVector vector, Location loc) { - vector = vector.Clone (); if (finally_vector != null) { - vector.MergeChild (finally_vector, false); int errors = Report.Errors; Parent.AddBreakOrigin (vector, loc); if (errors == Report.Errors) Report.Error (157, loc, "Control cannot leave the body of a finally clause"); } else { - vector.Location = loc; - vector.Next = break_origins; - break_origins = vector; + saved_origins = new BreakOrigin (saved_origins, vector, loc); } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); return true; } public override bool AddContinueOrigin (UsageVector vector, Location loc) { - vector = vector.Clone (); if (finally_vector != null) { - vector.MergeChild (finally_vector, false); int errors = Report.Errors; Parent.AddContinueOrigin (vector, loc); if (errors == Report.Errors) Report.Error (157, loc, "Control cannot leave the body of a finally clause"); } else { - vector.Location = loc; - vector.Next = continue_origins; - continue_origins = vector; + saved_origins = new ContinueOrigin (saved_origins, vector, loc); } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); return true; } - public override bool AddReturnOrigin (UsageVector vector, Location loc) + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) { - vector = vector.Clone (); if (finally_vector != null) { - vector.MergeChild (finally_vector, false); int errors = Report.Errors; - Parent.AddReturnOrigin (vector, loc); + Parent.AddReturnOrigin (vector, exit_stmt); if (errors == Report.Errors) - Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + exit_stmt.Error_FinallyClause (); } else { - vector.Location = loc; - vector.Next = return_origins; - return_origins = vector; + saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt); } + + // sets ec.NeedReturnLabel() + stmt.SomeCodeFollows (); return true; } @@ -882,64 +969,26 @@ namespace Mono.CSharp if (s != null) throw new InternalErrorException ("Shouldn't get here"); - vector = vector.Clone (); if (finally_vector != null) { - vector.MergeChild (finally_vector, false); int errors = Report.Errors; Parent.AddGotoOrigin (vector, goto_stmt); if (errors == Report.Errors) Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause"); } else { - goto_origins = new GotoOrigin (vector, goto_stmt, goto_origins); + saved_origins = new GotoOrigin (saved_origins, vector, goto_stmt); } return true; } - public override void StealFinallyClauses (ref ArrayList list) - { - if (list == null) - list = new ArrayList (); - list.Add (stmt); - emit_finally = false; - base.StealFinallyClauses (ref list); - } - - public bool EmitFinally { - get { return emit_finally; } - } - protected override UsageVector Merge () { - Report.Debug (2, " MERGING TRY/CATCH", Name); - UsageVector vector = UsageVector.MergeSiblings (catch_vectors, Location); - Report.Debug (2, " MERGING TRY/CATCH DONE", vector); + UsageVector vector = try_vector.Clone (); if (finally_vector != null) vector.MergeChild (finally_vector, false); - for (UsageVector origin = break_origins; origin != null; origin = origin.Next) { - if (finally_vector != null) - origin.MergeChild (finally_vector, false); - Parent.AddBreakOrigin (origin, origin.Location); - } - - for (UsageVector origin = continue_origins; origin != null; origin = origin.Next) { - if (finally_vector != null) - origin.MergeChild (finally_vector, false); - Parent.AddContinueOrigin (origin, origin.Location); - } - - for (UsageVector origin = return_origins; origin != null; origin = origin.Next) { - if (finally_vector != null) - origin.MergeChild (finally_vector, false); - Parent.AddReturnOrigin (origin, origin.Location); - } - - for (GotoOrigin origin = goto_origins; origin != null; origin = origin.Next) { - if (finally_vector != null) - origin.Vector.MergeChild (finally_vector, false); - Parent.AddGotoOrigin (origin.Vector, origin.GotoStmt); - } + for (SavedOrigin origin = saved_origins; origin != null; origin = origin.Next) + origin.PropagateFinally (finally_vector, Parent); return vector; } @@ -989,8 +1038,19 @@ namespace Mono.CSharp // public TypeInfo[] SubStructInfo; - protected readonly StructInfo struct_info; - private static Hashtable type_hash = new Hashtable (); + readonly StructInfo struct_info; + private static Hashtable type_hash; + + static TypeInfo () + { + Reset (); + } + + public static void Reset () + { + type_hash = new Hashtable (); + StructInfo.field_type_hash = new Hashtable (); + } public static TypeInfo GetTypeInfo (Type type) { @@ -1048,7 +1108,7 @@ namespace Mono.CSharp } } - protected TypeInfo (StructInfo struct_info, int offset) + TypeInfo (StructInfo struct_info, int offset) { this.struct_info = struct_info; this.Offset = offset; @@ -1089,9 +1149,16 @@ namespace Mono.CSharp FieldInfo field = struct_info.Fields [i]; if (!branching.IsFieldAssigned (vi, field.Name)) { - Report.Error (171, loc, - "Field `{0}' must be fully assigned before control leaves the constructor", - TypeManager.GetFullNameSignature (field)); + FieldBase fb = TypeManager.GetField (field); + if (fb is Property.BackingField) { + 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; } } @@ -1105,7 +1172,7 @@ namespace Mono.CSharp Type, Offset, Length, TotalLength); } - protected class StructInfo { + class StructInfo { public readonly Type Type; public readonly FieldInfo[] Fields; public readonly TypeInfo[] StructFields; @@ -1116,7 +1183,7 @@ namespace Mono.CSharp public readonly int TotalLength; public readonly bool HasStructFields; - private static Hashtable field_type_hash = new Hashtable (); + public static Hashtable field_type_hash; private Hashtable struct_field_hash; private Hashtable field_hash; @@ -1130,16 +1197,18 @@ namespace Mono.CSharp field_type_hash.Add (type, this); - if (type is TypeBuilder) { - TypeContainer tc = TypeManager.LookupTypeContainer (type); - - ArrayList fields = null; - if (tc != null) - fields = tc.Fields; + if (type.Module == RootContext.ToplevelTypes.Builder) { + TypeContainer tc = TypeManager.LookupTypeContainer (TypeManager.DropGenericTypeArguments (type)); ArrayList public_fields = new ArrayList (); ArrayList non_public_fields = new ArrayList (); + // + // TODO: tc != null is needed because FixedBuffers are not cached + // + if (tc != null) { + ArrayList fields = tc.Fields; + if (fields != null) { foreach (FieldBase field in fields) { if ((field.ModFlags & Modifiers.STATIC) != 0) @@ -1150,6 +1219,7 @@ namespace Mono.CSharp non_public_fields.Add (field.FieldBuilder); } } + } CountPublic = public_fields.Count; CountNonPublic = non_public_fields.Count; @@ -1158,12 +1228,10 @@ namespace Mono.CSharp Fields = new FieldInfo [Count]; public_fields.CopyTo (Fields, 0); non_public_fields.CopyTo (Fields, CountPublic); -#if GMCS_SOURCE } else if (type is GenericTypeParameterBuilder) { CountPublic = CountNonPublic = Count = 0; Fields = new FieldInfo [0]; -#endif } else { FieldInfo[] public_fields = type.GetFields ( BindingFlags.Instance|BindingFlags.Public); @@ -1242,6 +1310,9 @@ namespace Mono.CSharp TypeManager.IsBuiltinType (type)) return null; + if (TypeManager.IsGenericParameter (type)) + return null; + StructInfo info = (StructInfo) field_type_hash [type]; if (info != null) return info; @@ -1288,11 +1359,15 @@ namespace Mono.CSharp public readonly bool IsParameter; public readonly LocalInfo LocalInfo; - public readonly int ParameterIndex; readonly VariableInfo Parent; VariableInfo[] sub_info; + bool is_ever_assigned; + public bool IsEverAssigned { + get { return is_ever_assigned; } + } + protected VariableInfo (string name, Type type, int offset) { this.Name = name; @@ -1314,7 +1389,6 @@ namespace Mono.CSharp this.IsParameter = parent.IsParameter; this.LocalInfo = parent.LocalInfo; - this.ParameterIndex = parent.ParameterIndex; Initialize (); } @@ -1339,10 +1413,9 @@ namespace Mono.CSharp this.IsParameter = false; } - public VariableInfo (string name, Type type, int param_idx, int offset) - : this (name, type, offset) + public VariableInfo (ParametersCompiled ip, int i, int offset) + : this (ip.FixedParameters [i].Name, ip.Types [i], offset) { - this.ParameterIndex = param_idx; this.IsParameter = true; } @@ -1372,9 +1445,14 @@ namespace Mono.CSharp if (vector [Offset]) return true; - for (VariableInfo parent = Parent; parent != null; parent = parent.Parent) - if (vector [parent.Offset]) + // FIXME: Fix SetFieldAssigned to set the whole range like SetAssigned below. Then, get rid of this stanza + for (VariableInfo parent = Parent; parent != null; parent = parent.Parent) { + if (vector [parent.Offset]) { + // 'parent' is assigned, but someone forgot to note that all its components are assigned too + parent.SetAssigned (vector); return true; + } + } // Return unless this is a struct. if (!TypeInfo.IsStruct) @@ -1397,6 +1475,7 @@ namespace Mono.CSharp } vector [Offset] = true; + is_ever_assigned = true; return true; } @@ -1408,7 +1487,11 @@ namespace Mono.CSharp public void SetAssigned (MyBitVector vector) { - vector [Offset] = true; + if (Length == 1) + vector [Offset] = true; + else + vector.SetRange (Offset, Length); + is_ever_assigned = true; } public bool IsFieldAssigned (EmitContext ec, string name, Location loc) @@ -1448,6 +1531,7 @@ namespace Mono.CSharp return; vector [Offset + field_idx] = true; + is_ever_assigned = true; } public VariableInfo GetSubStruct (string name) @@ -1467,70 +1551,6 @@ namespace Mono.CSharp } } - // - // This is used by the flow code to hold the `layout' of the flow vector for - // all locals and all parameters (ie. we create one instance of this class for the - // locals and another one for the params). - // - public class VariableMap { - // - // The number of variables in the map. - // - public readonly int Count; - - // - // Total length of the flow vector for this map. - // - public readonly int Length; - - VariableInfo[] map; - - public VariableMap (Parameters ip) - { - Count = ip != null ? ip.Count : 0; - - // Dont bother allocating anything! - if (Count == 0) - return; - - Length = 0; - - for (int i = 0; i < Count; i++) { - Parameter.Modifier mod = ip.ParameterModifier (i); - - if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT) - continue; - - // Dont allocate till we find an out var. - if (map == null) - map = new VariableInfo [Count]; - - map [i] = new VariableInfo (ip.ParameterName (i), - TypeManager.GetElementType (ip.ParameterType (i)), i, Length); - - Length += map [i].Length; - } - } - - // - // Returns the VariableInfo for variable @index or null if we don't need to - // compute assignment info for this variable. - // - public VariableInfo this [int index] { - get { - if (map == null) - return null; - - return map [index]; - } - } - - public override string ToString () - { - return String.Format ("VariableMap ({0}:{1})", Count, Length); - } - } - // // This is a special bit vector which can inherit from another bit vector doing a // copy-on-write strategy. The inherited vector may have a smaller size than the @@ -1554,21 +1574,27 @@ namespace Mono.CSharp public MyBitVector (MyBitVector InheritsFrom, int Count) { if (InheritsFrom != null) - shared = InheritsFrom.Shared; + shared = InheritsFrom.MakeShared (Count); this.Count = Count; } - // Use this accessor to get a shareable copy of the underlying BitArray representation - BitArray Shared { - get { - // Post-condition: vector == null - if (shared == null) { - shared = vector; - vector = null; - } - return shared; + BitArray MakeShared (int new_count) + { + // Post-condition: vector == null + + // ensure we don't leak out dirty bits from the BitVector we inherited from + if (new_count > Count && + ((shared != null && shared.Count > Count) || + (shared == null && vector == null))) + initialize_vector (); + + if (vector != null) { + shared = vector; + vector = null; } + + return shared; } // @@ -1577,7 +1603,9 @@ namespace Mono.CSharp public bool this [int index] { get { if (index >= Count) - throw new ArgumentOutOfRangeException (); + // FIXME: Disabled due to missing anonymous method flow analysis + // throw new ArgumentOutOfRangeException (); + return true; if (vector != null) return vector [index]; @@ -1667,7 +1695,7 @@ namespace Mono.CSharp if (Count == o.Count) { if (vector == null) { if (shared == null) { - shared = new_vector.Shared; + shared = new_vector.MakeShared (Count); return this; } initialize_vector (); @@ -1724,12 +1752,36 @@ namespace Mono.CSharp return Count == 0 ? Empty : new MyBitVector (this, Count); } + public void SetRange (int offset, int length) + { + if (offset > Count || offset + length > Count) + throw new ArgumentOutOfRangeException (); + + if (shared == null && vector == null) + return; + + int i = 0; + if (shared != null) { + if (offset + length <= shared.Count) { + for (; i < length; ++i) + if (!shared [i+offset]) + break; + if (i == length) + return; + } + initialize_vector (); + } + for (; i < length; ++i) + vector [i+offset] = true; + + } + public void SetAll (bool value) { // Don't clobber Empty if (Count == 0) return; - shared = value ? null : Empty.Shared; + shared = value ? null : Empty.MakeShared (Count); vector = null; }