public bool IsFieldAssigned (VariableInfo var, string name) { if (/*!var.IsParameter &&*/ IsUnreachable) return true; return var.IsStructFieldAssigned (locals, name); }
public bool IsAssigned (VariableInfo vi) { return CurrentUsageVector.IsAssigned (vi, false); }
protected VariableInfo (VariableInfo parent, TypeInfo type) { this.Name = parent.Name; this.TypeInfo = type; this.Offset = parent.Offset + type.Offset; this.Parent = parent; this.Length = type.TotalLength; this.IsParameter = parent.IsParameter; Initialize (); }
public bool IsAssigned (VariableInfo var, bool ignoreReachability) { if (!ignoreReachability && !var.IsParameter && IsUnreachable) return true; return var.IsAssigned (locals); }
public void SetStructFieldAssigned (VariableInfo variable, string name) { variable.SetStructFieldAssigned (DefiniteAssignment, name); }
void ResolveMeta (BlockContext ec) { int orig_count = parameters.Count; for (int i = 0; i < orig_count; ++i) { Parameter.Modifier mod = parameters.FixedParameters[i].ModFlags; if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT) continue; VariableInfo vi = new VariableInfo (parameters, i, ec.FlowOffset); parameter_info[i].VariableInfo = vi; ec.FlowOffset += vi.Length; } }
// <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)) { FieldBase fb = TypeManager.GetField (field); if (fb != null && (fb.ModFlags & Modifiers.BACKING_FIELD) != 0) { 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; } } return ok; }
public bool IsStructFieldDefinitelyAssigned (VariableInfo variable, string name) { return variable.IsStructFieldAssigned (DefiniteAssignment, name); }
public override Expression DoResolve (EmitContext ec) { eclass = ExprClass.Variable; type = ec.ContainerType; if (ec.IsStatic){ Error (26, "Keyword this not valid in static code"); return null; } if (block != null) vi = block.ThisVariable; return this; }
public bool ResolveMeta (EmitContext ec, Parameters ip) { int errors = Report.Errors; int orig_count = parameters.Count; if (top_level_branching != null) return true; if (ip != null) parameters = ip; // Assert: orig_count != parameter.Count => orig_count == 0 if (orig_count != 0 && orig_count != parameters.Count) throw new InternalErrorException ("parameter information mismatch"); int offset = Parent == null ? 0 : Parent.AssignableSlots; for (int i = 0; i < orig_count; ++i) { Parameter.Modifier mod = parameters.FixedParameters [i].ModFlags; if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT) continue; VariableInfo vi = new VariableInfo (ip, i, offset); parameter_info [i].VariableInfo = vi; offset += vi.Length; } ResolveMeta (ec, offset); top_level_branching = ec.StartFlowBranching (this); return Report.Errors == errors; }
// Setting `is_readonly' to false will allow you to create a writable // reference to a read-only variable. This is used by foreach and using. public LocalVariableReference (Block block, string name, Location l, VariableInfo variable_info, bool is_readonly) : this (block, name, l) { this.variable_info = variable_info; this.is_readonly = is_readonly; }
public void SetStructFieldAssigned(VariableInfo variable, string name) { variable.SetStructFieldAssigned(DefiniteAssignment, name); }
public void SetVariableAssigned(VariableInfo variable, bool generatedAssignment = false) { variable.SetAssigned(DefiniteAssignment, generatedAssignment); }
public void SetAssigned (VariableInfo vi) { CurrentUsageVector.SetAssigned (vi); }
public bool ResolveBase (EmitContext ec) { if (eclass != ExprClass.Invalid) return true; eclass = ExprClass.Variable; if (ec.TypeContainer.CurrentType != null) type = ec.TypeContainer.CurrentType; else type = ec.ContainerType; if (!IsThisAvailable (ec)) { if (ec.IsStatic) { Error (26, "Keyword `this' is not valid in a static property, static method, or static field initializer"); } else { Report.Error (1673, loc, "Anonymous methods inside structs cannot access instance members of `this'. " + "Consider copying `this' to a local variable outside the anonymous method and using the local instead"); } } is_struct = ec.TypeContainer is Struct; if (block != null) { if (block.Toplevel.ThisVariable != null) variable_info = block.Toplevel.ThisVariable.VariableInfo; AnonymousExpression am = ec.CurrentAnonymousMethod; if (am != null) { // // this is hoisted to very top level block // if (ec.IsVariableCapturingRequired) { // // TODO: it should be optimized, see test-anon-75.cs // // `this' variable has its own scope which is mostly empty // and causes creation of extraneous storey references. // Also it's hard to remove `this' dependencies when we Undo // this access. // AnonymousMethodStorey scope = TopToplevelBlock.Explicit.CreateAnonymousMethodStorey (ec); if (HoistedVariable == null) { TopToplevelBlock.HoistedThisVariable = scope.CaptureThis (ec, this); } } } } return true; }
public bool IsStructFieldDefinitelyAssigned(VariableInfo variable, string name) { return(variable.IsStructFieldAssigned(DefiniteAssignment, name)); }
public bool ResolveBase (ResolveContext ec) { if (eclass != ExprClass.Invalid) return true; eclass = ExprClass.Variable; type = ec.CurrentType; if (!IsThisAvailable (ec)) { if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) { ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer"); } else if (ec.CurrentAnonymousMethod != null) { ec.Report.Error (1673, loc, "Anonymous methods inside structs cannot access instance members of `this'. " + "Consider copying `this' to a local variable outside the anonymous method and using the local instead"); } else { ec.Report.Error (27, loc, "Keyword `this' is not available in the current context"); } } is_struct = type.IsValueType; if (block != null) { if (block.Toplevel.ThisVariable != null) variable_info = block.Toplevel.ThisVariable.VariableInfo; AnonymousExpression am = ec.CurrentAnonymousMethod; if (am != null && ec.IsVariableCapturingRequired) { am.SetHasThisAccess (); } } return true; }
public void SetVariableAssigned (VariableInfo variable, bool generatedAssignment = false) { variable.SetAssigned (DefiniteAssignment, generatedAssignment); }
Expression DoResolve (EmitContext ec, bool lvalue_instance, bool out_access) { if (!FieldInfo.IsStatic){ if (InstanceExpression == null){ // // This can happen when referencing an instance field using // a fully qualified type expression: TypeName.InstanceField = xxx // SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; } // Resolve the field's instance expression while flow analysis is turned // off: when accessing a field "a.b", we must check whether the field // "a.b" is initialized, not whether the whole struct "a" is initialized. if (lvalue_instance) { using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) { Expression right_side = out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc); } } else { ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis; InstanceExpression = InstanceExpression.Resolve (ec, rf); } if (InstanceExpression == null) return null; using (ec.Set (EmitContext.Flags.OmitStructFlowAnalysis)) { InstanceExpression.CheckMarshalByRefAccess (ec); } } // TODO: the code above uses some non-standard multi-resolve rules if (eclass != ExprClass.Invalid) return this; if (!ec.IsInObsoleteScope) { FieldBase f = TypeManager.GetField (FieldInfo); if (f != null) { f.CheckObsoleteness (loc); } else { ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo); if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc); } } IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo); IVariableReference var = InstanceExpression as IVariableReference; if (fb != null) { IFixedExpression fe = InstanceExpression as IFixedExpression; if (!ec.InFixedInitializer && (fe == null || !fe.IsFixed)) { Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); } if (InstanceExpression.eclass != ExprClass.Variable) { Report.SymbolRelatedToPreviousError (FieldInfo); Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", TypeManager.GetFullNameSignature (FieldInfo)); } else if (var != null && var.IsHoisted) { AnonymousMethodExpression.Error_AddressOfCapturedVar (var, loc); } return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); } eclass = ExprClass.Variable; // If the instance expression is a local variable or parameter. if (var == null || var.VariableInfo == null) return this; VariableInfo vi = var.VariableInfo; if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc)) return null; variable_info = vi.GetSubStruct (FieldInfo.Name); eclass = ExprClass.Variable; return this; }
public void PrepareForFlowAnalysis (BlockContext bc) { // // No need for definitely assigned check for these guys // if ((flags & (Flags.Constant | Flags.ReadonlyMask | Flags.CompilerGenerated)) != 0) return; VariableInfo = new VariableInfo (this, bc.FlowOffset); bc.FlowOffset += VariableInfo.Length; }
Expression DoResolve(ResolveContext ec, bool lvalue_instance, bool out_access) { if (!IsStatic){ if (InstanceExpression == null){ // // This can happen when referencing an instance field using // a fully qualified type expression: TypeName.InstanceField = xxx // SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; } // Resolve the field's instance expression while flow analysis is turned // off: when accessing a field "a.b", we must check whether the field // "a.b" is initialized, not whether the whole struct "a" is initialized. if (lvalue_instance) { using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { Expression right_side = out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; if (InstanceExpression != EmptyExpression.Null) InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); } } else { if (InstanceExpression != EmptyExpression.Null) { using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue); } } } if (InstanceExpression == null) return null; using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { InstanceExpression.CheckMarshalByRefAccess (ec); } } if (!ec.IsObsolete) { ObsoleteAttribute oa = spec.GetAttributeObsolete (); if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (spec), loc, ec.Report); } var fb = spec as FixedFieldSpec; IVariableReference var = InstanceExpression as IVariableReference; if (fb != null) { IFixedExpression fe = InstanceExpression as IFixedExpression; if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); } if (InstanceExpression.eclass != ExprClass.Variable) { ec.Report.SymbolRelatedToPreviousError (spec); ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", TypeManager.GetFullNameSignature (spec)); } else if (var != null && var.IsHoisted) { AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc); } return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); } eclass = ExprClass.Variable; // If the instance expression is a local variable or parameter. if (var == null || var.VariableInfo == null) return this; VariableInfo vi = var.VariableInfo; if (!vi.IsFieldAssigned (ec, Name, loc)) return null; variable_info = vi.GetSubStruct (Name); return this; }
// <summary> // A struct's constructor must always assign all fields. // This method checks whether it actually does so. // </summary> public bool IsFullyInitialized (BlockContext ec, VariableInfo vi, Location loc) { if (struct_info == null) return true; bool ok = true; FlowBranching branching = ec.CurrentBranching; for (int i = 0; i < struct_info.Count; i++) { var field = struct_info.Fields [i]; if (!branching.IsStructFieldAssigned (vi, field.Name)) { if (field.MemberDefinition is Property.BackingField) { ec.Report.Error (843, loc, "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer", field.GetSignatureForError ()); } else { ec.Report.Error (171, loc, "Field `{0}' must be fully assigned before control leaves the constructor", field.GetSignatureForError ()); } ok = false; } } return ok; }
// <summary> // A struct's constructor must always assign all fields. // This method checks whether it actually does so. // </summary> public bool IsFullyInitialized (FlowAnalysisContext fc, VariableInfo vi, Location loc) { if (struct_info == null) return true; bool ok = true; for (int i = 0; i < struct_info.Count; i++) { var field = struct_info.Fields[i]; if (!fc.IsStructFieldDefinitelyAssigned (vi, field.Name)) { var bf = field.MemberDefinition as Property.BackingFieldDeclaration; if (bf != null) { if (bf.Initializer != null) continue; fc.Report.Error (843, loc, "An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer", field.GetSignatureForError ()); ok = false; continue; } fc.Report.Error (171, loc, "Field `{0}' must be fully assigned before control leaves the constructor", field.GetSignatureForError ()); ok = false; } } return ok; }
protected void Initialize () { TypeInfo[] sub_fields = TypeInfo.SubStructInfo; if (sub_fields != null) { sub_info = new VariableInfo [sub_fields.Length]; for (int i = 0; i < sub_fields.Length; i++) { if (sub_fields [i] != null) sub_info [i] = new VariableInfo (this, sub_fields [i]); } } else sub_info = new VariableInfo [0]; }
public static VariableInfo Create (BlockContext bc, LocalVariable variable) { var info = new VariableInfo (variable.Name, variable.Type, bc.AssignmentInfoOffset, bc); bc.AssignmentInfoOffset += info.Length; return info; }
public void SetAssigned (VariableInfo var) { if (!var.IsParameter && IsUnreachable) return; var.SetAssigned (locals); }
public static VariableInfo Create (BlockContext bc, Parameter parameter) { var info = new VariableInfo (parameter.Name, parameter.Type, bc.AssignmentInfoOffset, bc) { IsParameter = true }; bc.AssignmentInfoOffset += info.Length; return info; }
public void SetFieldAssigned (VariableInfo var, string name) { if (/*!var.IsParameter &&*/ IsUnreachable) return; var.SetStructFieldAssigned (locals, name); }
bool ResolveMeta (BlockContext ec, ParametersCompiled ip) { int errors = ec.Report.Errors; int orig_count = parameters.Count; if (ip != null) parameters = ip; // Assert: orig_count != parameter.Count => orig_count == 0 if (orig_count != 0 && orig_count != parameters.Count) throw new InternalErrorException ("parameter information mismatch"); int offset = Parent == null ? 0 : Parent.AssignableSlots; for (int i = 0; i < orig_count; ++i) { Parameter.Modifier mod = parameters.FixedParameters [i].ModFlags; if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT) continue; VariableInfo vi = new VariableInfo (ip, i, offset); parameter_info [i].VariableInfo = vi; offset += vi.Length; } ResolveMeta (ec, offset); return ec.Report.Errors == errors; }
public bool IsStructFieldAssigned (VariableInfo vi, string field_name) { return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name); }
public bool IsDefinitelyAssigned (VariableInfo variable) { return variable.IsAssigned (DefiniteAssignment); }
public void SetFieldAssigned (VariableInfo vi, string name) { CurrentUsageVector.SetFieldAssigned (vi, name); }
public bool IsDefinitelyAssigned(VariableInfo variable) { return(variable.IsAssigned(DefiniteAssignment)); }