📄 flowanalysis.cs
字号:
else if (!is_return && ((Type == BranchingType.Loop) || (Type == BranchingType.Switch))) return false; else if (Parent != null) return Parent.InTryOrCatch (is_return); else return false; } public virtual bool InTryWithCatch () { if (Parent != null) return Parent.InTryWithCatch (); return false; } public virtual bool InLoop () { if (Type == BranchingType.Loop) return true; else if (Parent != null) return Parent.InLoop (); else return false; } public virtual bool InSwitch () { if (Type == BranchingType.Switch) return true; else if (Parent != null) return Parent.InSwitch (); else return false; } public virtual bool BreakCrossesTryCatchBoundary () { if ((Type == BranchingType.Loop) || (Type == BranchingType.Switch)) return false; else if (Parent != null) return Parent.BreakCrossesTryCatchBoundary (); else return false; } public virtual void AddFinallyVector (UsageVector vector) { if (Parent != null) Parent.AddFinallyVector (vector); else if ((Block == null) || !Block.IsDestructor) throw new NotSupportedException (); } public virtual void AddBreakVector (UsageVector vector) { if (Parent != null) Parent.AddBreakVector (vector); else if ((Block == null) || !Block.IsDestructor) throw new NotSupportedException (); } public virtual void StealFinallyClauses (ref ArrayList list) { if (Parent != null) Parent.StealFinallyClauses (ref list); } public bool IsAssigned (VariableInfo vi) { return CurrentUsageVector.IsAssigned (vi); } public bool IsFieldAssigned (VariableInfo vi, string field_name) { if (CurrentUsageVector.IsAssigned (vi)) return true; return CurrentUsageVector.IsFieldAssigned (vi, field_name); } public void SetAssigned (VariableInfo vi) { CurrentUsageVector.SetAssigned (vi); } public void SetFieldAssigned (VariableInfo vi, string name) { CurrentUsageVector.SetFieldAssigned (vi, name); } public override string ToString () { StringBuilder sb = new StringBuilder (); sb.Append (GetType ()); sb.Append (" ("); sb.Append (id); sb.Append (","); sb.Append (Type); if (Block != null) { sb.Append (" - "); sb.Append (Block.ID); sb.Append (" - "); sb.Append (Block.StartLocation); } sb.Append (" - "); // sb.Append (Siblings.Length); // sb.Append (" - "); sb.Append (CurrentUsageVector); sb.Append (")"); return sb.ToString (); } public string Name { get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); } } } public class FlowBranchingBlock : FlowBranching { UsageVector sibling_list = null; public FlowBranchingBlock (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) : base (parent, type, stype, block, loc) { } public override UsageVector CurrentUsageVector { get { return sibling_list; } } protected override void AddSibling (UsageVector sibling) { sibling.Next = sibling_list; sibling_list = sibling; } public override LabeledStatement LookupLabel (string name, Location loc) { if (Block == null) return base.LookupLabel (name, loc); LabeledStatement s = Block.LookupLabel (name); if (s != null) return s; return base.LookupLabel (name, loc); } public override void Label (UsageVector origin_vectors) { if (!CurrentUsageVector.Reachability.IsUnreachable) { UsageVector vector = CurrentUsageVector.Clone (); vector.Next = origin_vectors; origin_vectors = vector; } CurrentUsageVector.MergeJumpOrigins (origin_vectors); } protected override UsageVector Merge () { return Merge (sibling_list); } } public class FlowBranchingLoop : FlowBranchingBlock { UsageVector break_origins; public FlowBranchingLoop (FlowBranching parent, Block block, Location loc) : base (parent, BranchingType.Loop, SiblingType.Conditional, block, loc) { } public override void AddBreakVector (UsageVector vector) { vector = vector.Clone (); vector.Next = break_origins; break_origins = vector; } protected override UsageVector Merge () { UsageVector vector = base.Merge (); vector.MergeBreakOrigins (this, break_origins); return vector; } } public class FlowBranchingSwitch : FlowBranchingBlock { UsageVector break_origins; public FlowBranchingSwitch (FlowBranching parent, Block block, Location loc) : base (parent, BranchingType.Switch, SiblingType.SwitchSection, block, loc) { } public override void AddBreakVector (UsageVector vector) { vector = vector.Clone (); vector.Next = break_origins; break_origins = vector; } protected override UsageVector Merge () { UsageVector vector = base.Merge (); vector.MergeBreakOrigins (this, break_origins); return vector; } } public class FlowBranchingException : FlowBranching { ExceptionStatement stmt; UsageVector current_vector; UsageVector catch_vectors; UsageVector finally_vector; UsageVector finally_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) { if (sibling.Type == SiblingType.Try) { sibling.Next = catch_vectors; catch_vectors = sibling; } else if (sibling.Type == SiblingType.Catch) { sibling.Next = catch_vectors; catch_vectors = sibling; } else if (sibling.Type == SiblingType.Finally) { sibling.MergeFinallyOrigins (finally_origins); finally_vector = sibling; } else throw new InvalidOperationException (); current_vector = sibling; } public override UsageVector CurrentUsageVector { get { return current_vector; } } public override bool InTryOrCatch (bool is_return) { return finally_vector == null; } public override bool InTryWithCatch () { if (finally_vector == null) { Try t = stmt as Try; if (t != null && t.HasCatch) return true; } if (Parent != null) return Parent.InTryWithCatch (); return false; } public override bool BreakCrossesTryCatchBoundary () { return true; } public override void AddFinallyVector (UsageVector vector) { vector = vector.Clone (); vector.Next = finally_origins; finally_origins = vector; } 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; } } public override LabeledStatement LookupLabel (string name, Location loc) { if (current_vector.Block == null) return base.LookupLabel (name, loc); LabeledStatement s = current_vector.Block.LookupLabel (name); if (s != null) return s; if (finally_vector != null) { Report.Error (157, loc, "Control cannot leave the body of a finally clause"); return null; } return base.LookupLabel (name, loc); } public override void Label (UsageVector origin_vectors) { CurrentUsageVector.MergeJumpOrigins (origin_vectors); } protected override UsageVector Merge () { UsageVector vector = Merge (catch_vectors); vector.MergeFinally (this, finally_vector, finally_origins); return vector; } } // <summary> // This is used by the flow analysis code to keep track of the type of local variables // and variables. // // The flow code uses a BitVector to keep track of whether a variable has been assigned // or not. This is easy for fundamental types (int, char etc.) or reference types since // you can only assign the whole variable as such. // // For structs, we also need to keep track of all its fields. To do this, we allocate one // bit for the struct itself (it's used if you assign/access the whole struct) followed by // one bit for each of its fields. // // This class computes this `layout' for each type. // </summary> public class TypeInfo { public readonly Type Type; // <summary> // Total number of bits a variable of this type consumes in the flow vector. // </summary> public readonly int TotalLength; // <summary> // Number of bits the simple fields of a variable of this type consume // in the flow vector. // </summary> public readonly int Length; // <summary> // This is only used by sub-structs. // </summary> public readonly int Offset; // <summary> // If this is a struct. // </summary> public readonly bool IsStruct; // <summary> // If this is a struct, all fields which are structs theirselves. // </summary> public TypeInfo[] SubStructInfo; protected readonly StructInfo struct_info; private static Hashtable type_hash = new Hashtable (); public static TypeInfo GetTypeInfo (Type type) { TypeInfo info = (TypeInfo) type_hash [type]; if (info != null) return info; info = new TypeInfo (type); type_hash.Add (type, info); return info; } public static TypeInfo GetTypeInfo (TypeContainer tc) { TypeInfo info = (TypeInfo) type_hash [tc.TypeBuilder]; if (info != null) return info; info = new TypeInfo (tc); type_hash.Add (tc.TypeBuilder, info); return info; } private TypeInfo (Type type) { this.Type = type; struct_info = StructInfo.GetStructInfo (type); if (struct_info != null) { Length = struct_info.Length; TotalLength = struct_info.TotalLength; SubStructInfo = struct_info.StructFields; IsStruct = true; } else { Length = 0; TotalLength = 1; IsStruct = false; } } private TypeInfo (TypeContainer tc) { this.Type = tc.TypeBuilder; struct_info = StructInfo.GetStructInfo (tc); if (struct_info != null) { Length = struct_info.Length; TotalLength = struct_info.TotalLength; SubStructInfo = struct_info.StructFields; IsStruct = true; } else { Length = 0; TotalLength = 1; IsStruct = false; } } protected TypeInfo (StructInfo struct_info, int offset) { this.struct_info = struct_info; this.Offset = offset; this.Length = struct_info.Length; this.TotalLength = struct_info.TotalLength; this.SubStructInfo = struct_info.StructFields; this.Type = struct_info.Type; this.IsStruct = true; } public int GetFieldIndex (string name) { if (struct_info == null) return 0; return struct_info [name]; } public TypeInfo GetSubStruct (string name) { if (struct_info == null) return null; return struct_info.GetStructField (name); } // <summary> // A struct's constructor must always assign all fields. // This method checks whether it actually does so. // </summary> public bool IsFullyInitialized (FlowBranching branching, VariableInfo vi, Location loc) { if (struct_info == null) return true; bool ok = true; for (int i = 0; i < struct_info.Count; i++) { FieldInfo field = struct_info.Fields [i]; if (!branching.IsFieldAssigned (vi, field.Name)) { Report.Error (171, loc, "Field `{0}' must be fully assigned before control leaves the constructor", TypeManager.GetFullNameSignature (field)); ok = false; } } return ok; } public override string ToString () { return String.Format ("TypeInfo ({0}:{1}:{2}:{3})", Type, Offset, Length, TotalLength); } protected class StructInfo { public readonly Type Type; public readonly FieldInfo[] Fields; public readonly TypeInfo[] StructFields; public readonly int Count; public readonly int CountPublic; public readonly int CountNonPublic; public readonly int Length; public readonly int TotalLength; public readonly bool HasStructFields; private static Hashtable field_type_hash = new Hashtable (); private Hashtable struct_field_hash; private Hashtable field_hash; protected bool InTransit = false; // Private constructor. To save memory usage, we only need to create one instance // of this class per struct type. private StructInfo (Type type) { this.Type = type; field_type_hash.Add (type, this); if (type is TypeBuilder) { TypeContainer tc = TypeManager.LookupTypeContainer (type); ArrayList fields = null; if (tc != null) fields = tc.Fields; ArrayList public_fields = new ArrayList (); ArrayList non_public_fields = new ArrayList (); if (fields != null) { foreach (FieldMember field in fields) { if ((field.ModFlags & Modifiers.STATIC) != 0) continue; if ((field.ModFlags & Modifiers.PUBLIC) != 0) public_fields.Add (field.FieldBuilder); else non_public_fields.Add (field.FieldBuilder); } } CountPublic = public_fields.Count; CountNonPublic = non_public_fields.Count; Count = CountPublic + CountNonPublic; Fields = new FieldInfo [Count]; public_fields.CopyTo (Fields, 0); non_public_fields.CopyTo (Fields, CountPublic); } else { FieldInfo[] public_fields = type.GetFields ( BindingFlags.Instance|BindingFlags.Public); FieldInfo[] non_public_fields = type.GetFields ( BindingFlags.Instance|BindingFlags.NonPublic); CountPublic = public_fields.Length; CountNonPublic = non_public_fields.Length; Count = CountPublic + CountNonPublic; Fields = new FieldInfo [Count]; public_fields.CopyTo (Fields, 0); non_public_fields.CopyTo (Fields, CountPublic); } struct_field_hash = new Hashtable (); field_hash = new Hashtable (); Length = 0; StructFields = new TypeInfo [Count]; StructInfo[] sinfo = new StructInfo [Count]; InTransit = true; for (int i = 0; i < Count; i++) { FieldInfo field = (FieldInfo) Fields [i]; sinfo [i] = GetStructInfo (field.FieldType); if (sinfo [i] == null) field_hash.Add (field.Name, ++Length); else if (sinfo [i].InTransit) { Report.Error (523, String.Format ( "Struct member `{0}.{1}' of type `{2}' causes " +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -