X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fflowanalysis.cs;h=2213d36e59eacb468a4ba34648963c64140dc6bc;hb=3c28dc153645532e837e42ecbd8979d05dc944a8;hp=725a6346f30fa712010f229980074bf2f63a75ae;hpb=a6eeaa200ec727cbf8267463651ddb4fa9f00243;p=mono.git diff --git a/mcs/mcs/flowanalysis.cs b/mcs/mcs/flowanalysis.cs index 725a6346f30..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; @@ -52,7 +53,10 @@ namespace Mono.CSharp Switch, // The toplevel block of a function - Toplevel + Toplevel, + + // An iterator block + Iterator } // @@ -73,6 +77,7 @@ namespace Mono.CSharp case BranchingType.Exception: case BranchingType.Labeled: case BranchingType.Toplevel: + case BranchingType.TryCatch: throw new InvalidOperationException (); case BranchingType.Switch: @@ -87,9 +92,6 @@ namespace Mono.CSharp case BranchingType.Embedded: return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc); - case BranchingType.TryCatch: - return new FlowBranchingTryCatch (parent, loc); - default: return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc); } @@ -312,6 +314,10 @@ namespace Mono.CSharp locals |= child.locals; + // throw away un-necessary information about variables in child blocks + if (locals.Count != CountLocals) + locals = new MyBitVector (locals, CountLocals); + if (overwrite) is_unreachable = new_isunr; else @@ -402,32 +408,19 @@ namespace Mono.CSharp protected abstract UsageVector Merge (); - // - // Merge a child branching. - // public UsageVector MergeChild (FlowBranching child) { - bool overwrite = false; - - switch (child.Type) { - case BranchingType.Labeled: - overwrite = true; - break; - case BranchingType.Block: - if (child.Block != null && child.Block != child.Block.Explicit) - overwrite = true; - break; - } - - 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.CheckRethrow (loc); + } + + public virtual bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) { - return Parent.InTryWithCatch (); + return Parent.AddResumePoint (stmt, loc, out pc); } // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) @@ -454,12 +447,6 @@ namespace Mono.CSharp return Parent.AddGotoOrigin (vector, goto_stmt); } - // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) - public virtual bool StealFinallyClauses (ref ArrayList list) - { - return Parent.StealFinallyClauses (ref list); - } - public bool IsAssigned (VariableInfo vi) { return CurrentUsageVector.IsAssigned (vi, false); @@ -523,7 +510,7 @@ namespace Mono.CSharp protected override void AddSibling (UsageVector sibling) { - if (sibling.Type == SiblingType.Block && sibling_list != null) + 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; @@ -644,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; @@ -653,11 +656,17 @@ namespace Mono.CSharp { } - public override bool InTryWithCatch () + public override bool CheckRethrow (Location loc) { + Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause"); return false; } + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + throw new InternalErrorException ("A yield in a non-iterator block"); + } + public override bool AddBreakOrigin (UsageVector vector, Location loc) { Report.Error (139, loc, "No enclosing loop out of which to break or continue"); @@ -679,11 +688,6 @@ namespace Mono.CSharp return false; } - public override bool StealFinallyClauses (ref ArrayList list) - { - return false; - } - public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) { string name = goto_stmt.Target; @@ -722,31 +726,49 @@ namespace Mono.CSharp public class FlowBranchingTryCatch : FlowBranchingBlock { - public FlowBranchingTryCatch (FlowBranching parent, Location loc) - : base (parent, BranchingType.Block, SiblingType.Try, null, loc) + 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 InTryWithCatch () + 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 stmt) + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) { - Parent.AddReturnOrigin (vector, stmt); + Parent.AddReturnOrigin (vector, exit_stmt); + stmt.SomeCodeFollows (); return true; } @@ -755,12 +777,6 @@ namespace Mono.CSharp Parent.AddGotoOrigin (vector, goto_stmt); return true; } - - public override bool StealFinallyClauses (ref ArrayList list) - { - Parent.StealFinallyClauses (ref list); - return true; - } } public class FlowBranchingException : FlowBranching @@ -771,10 +787,10 @@ namespace Mono.CSharp UsageVector finally_vector; abstract class SavedOrigin { - public SavedOrigin Next; - public UsageVector Vector; + public readonly SavedOrigin Next; + public readonly UsageVector Vector; - public SavedOrigin (SavedOrigin next, UsageVector vector) + protected SavedOrigin (SavedOrigin next, UsageVector vector) { Next = next; Vector = vector.Clone (); @@ -849,15 +865,12 @@ namespace Mono.CSharp SavedOrigin saved_origins; - bool emit_finally; - public FlowBranchingException (FlowBranching parent, ExceptionStatement stmt) : base (parent, BranchingType.Exception, SiblingType.Try, null, stmt.loc) { this.stmt = stmt; - this.emit_finally = true; } protected override void AddSibling (UsageVector sibling) @@ -879,6 +892,29 @@ namespace Mono.CSharp get { return current_vector; } } + public override bool CheckRethrow (Location loc) + { + 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; + } + + 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) { if (finally_vector != null) { @@ -889,6 +925,9 @@ namespace Mono.CSharp } else { saved_origins = new BreakOrigin (saved_origins, vector, loc); } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); return true; } @@ -902,19 +941,25 @@ namespace Mono.CSharp } else { 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, ExitStatement stmt) + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) { if (finally_vector != null) { int errors = Report.Errors; - Parent.AddReturnOrigin (vector, stmt); + Parent.AddReturnOrigin (vector, exit_stmt); if (errors == Report.Errors) - stmt.Error_FinallyClause (); + exit_stmt.Error_FinallyClause (); } else { - saved_origins = new ReturnOrigin (saved_origins, vector, stmt); + saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt); } + + // sets ec.NeedReturnLabel() + stmt.SomeCodeFollows (); return true; } @@ -935,20 +980,6 @@ namespace Mono.CSharp return true; } - public override bool StealFinallyClauses (ref ArrayList list) - { - if (list == null) - list = new ArrayList (); - list.Add (stmt); - emit_finally = false; - base.StealFinallyClauses (ref list); - return true; - } - - public bool EmitFinally { - get { return emit_finally; } - } - protected override UsageVector Merge () { UsageVector vector = try_vector.Clone (); @@ -1007,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) { @@ -1066,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; @@ -1107,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; } } @@ -1123,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; @@ -1134,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; @@ -1148,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) @@ -1168,6 +1219,7 @@ namespace Mono.CSharp non_public_fields.Add (field.FieldBuilder); } } + } CountPublic = public_fields.Count; CountNonPublic = non_public_fields.Count; @@ -1176,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); @@ -1260,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; @@ -1360,8 +1413,8 @@ namespace Mono.CSharp this.IsParameter = false; } - public VariableInfo (Parameters ip, int i, int offset) - : this (ip.ParameterName (i), TypeManager.GetElementType (ip.ParameterType (i)), offset) + public VariableInfo (ParametersCompiled ip, int i, int offset) + : this (ip.FixedParameters [i].Name, ip.Types [i], offset) { this.IsParameter = true; } @@ -1521,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; } // @@ -1544,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]; @@ -1634,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 (); @@ -1720,7 +1781,7 @@ namespace Mono.CSharp // Don't clobber Empty if (Count == 0) return; - shared = value ? null : Empty.Shared; + shared = value ? null : Empty.MakeShared (Count); vector = null; }