call.EmitPredefined (ec, oper, arguments, loc);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ arguments.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
#if STATIC
Expr.EmitSideEffect (ec);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (Oper == Operator.AddressOf) {
+ var vr = Expr as VariableReference;
+ if (vr != null && vr.VariableInfo != null)
+ fc.SetVariableAssigned (vr.VariableInfo);
+
+ return;
+ }
+
+ Expr.FlowAnalysis (fc);
+ }
+
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
EmitCode (ec, false);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
return this;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
protected abstract string OperatorName { get; }
protected override void CloneTo (CloneContext clonectx, Expression t)
Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ left.FlowAnalysis (fc);
+ right.FlowAnalysis (fc);
+ }
+
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ arguments.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
if (arguments.Count != 2)
protected override Expression DoResolve (ResolveContext ec)
{
expr = expr.Resolve (ec);
-
- //
- // Unreachable code needs different resolve path. For instance for await
- // expression to not generate unreachable resumable statement
- //
- Constant c = expr as Constant;
- if (c != null && ec.CurrentBranching != null) {
- bool unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-
- if (c.IsDefaultValue) {
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true;
- true_expr = true_expr.Resolve (ec);
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable;
-
- false_expr = false_expr.Resolve (ec);
- } else {
- true_expr = true_expr.Resolve (ec);
-
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true;
- false_expr = false_expr.Resolve (ec);
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable;
- }
- } else {
- true_expr = true_expr.Resolve (ec);
- false_expr = false_expr.Resolve (ec);
- }
+ true_expr = true_expr.Resolve (ec);
+ false_expr = false_expr.Resolve (ec);
if (true_expr == null || false_expr == null || expr == null)
return null;
true_type.GetSignatureForError (), false_type.GetSignatureForError ());
return null;
}
- }
+ }
+ Constant c = expr as Constant;
if (c != null) {
bool is_false = c.IsDefaultValue;
ec.MarkLabel (end_target);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ var expr_fc = fc.DefiniteAssignment;
+
+ fc.DefiniteAssignment = new DefiniteAssignmentBitSet (expr_fc);
+ true_expr.FlowAnalysis (fc);
+ var true_fc = fc.DefiniteAssignment;
+
+ fc.DefiniteAssignment = new DefiniteAssignmentBitSet (expr_fc);
+ false_expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignment &= true_fc;
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
Conditional target = (Conditional) t;
#region Abstract
public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
public abstract void SetHasAddressTaken ();
- public abstract void VerifyDefiniteAssignment (ResolveContext rc);
public abstract bool IsLockedByStatement { get; set; }
#endregion
- public override void VerifyDefiniteAssignment (ResolveContext rc)
+ public override void FlowAnalysis (FlowAnalysisContext fc)
{
VariableInfo variable_info = VariableInfo;
if (variable_info == null)
return;
- if (variable_info.IsAssigned (rc))
+ if (fc.IsDefinitelyAssigned (variable_info))
return;
- rc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
- variable_info.SetAssigned (rc);
+ fc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
+ variable_info.SetAssigned (fc.DefiniteAssignment, true);
}
public override void SetHasAddressTaken ()
{
local_info.SetIsUsed ();
- VerifyDefiniteAssignment (ec);
-
DoResolveBase (ec);
return this;
}
local_info.SetIsUsed ();
if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) {
- int code;
- string msg;
- if (rhs == EmptyExpression.OutAccess) {
- code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
- } else if (rhs == EmptyExpression.LValueMemberAccess) {
- code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
- } else if (rhs == EmptyExpression.LValueMemberOutAccess) {
- code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
- } else if (rhs == EmptyExpression.UnaryAddress) {
- code = 459; msg = "Cannot take the address of {1} `{0}'";
+ if (rhs == EmptyExpression.LValueMemberAccess) {
+ // CS1654 already reported
} else {
- code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
+ int code;
+ string msg;
+ if (rhs == EmptyExpression.OutAccess) {
+ code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
+ } else if (rhs == EmptyExpression.LValueMemberOutAccess) {
+ code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
+ } else if (rhs == EmptyExpression.UnaryAddress) {
+ code = 459; msg = "Cannot take the address of {1} `{0}'";
+ } else {
+ code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
+ }
+ ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
}
- ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
- } else if (VariableInfo != null) {
- VariableInfo.SetAssigned (ec);
}
if (eclass == ExprClass.Unresolved)
Parameter.HasAddressTaken = true;
}
- void SetAssigned (ResolveContext ec)
- {
- if (Parameter.HoistedVariant != null)
- Parameter.HoistedVariant.IsAssigned = true;
-
- if (HasOutModifier && ec.DoFlowAnalysis)
- ec.CurrentBranching.SetAssigned (VariableInfo);
- }
-
bool DoResolveBase (ResolveContext ec)
{
if (eclass != ExprClass.Unresolved)
if (!DoResolveBase (ec))
return null;
- VerifyDefiniteAssignment (ec);
return this;
}
if (!DoResolveBase (ec))
return null;
- SetAssigned (ec);
+ if (Parameter.HoistedVariant != null)
+ Parameter.HoistedVariant.IsAssigned = true;
+
return base.DoResolveLValue (ec, right_side);
}
- public override void VerifyDefiniteAssignment (ResolveContext rc)
+ public override void FlowAnalysis (FlowAnalysisContext fc)
{
VariableInfo variable_info = VariableInfo;
if (variable_info == null)
return;
- if (variable_info.IsAssigned (rc))
+ if (fc.IsDefinitelyAssigned (variable_info))
return;
- rc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
- variable_info.SetAssigned (rc);
+ fc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
+ fc.SetVariableAssigned (variable_info);
}
}
return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (mg.IsConditionallyExcluded)
+ return;
+
+ mg.FlowAnalysis (fc);
+
+ if (arguments != null)
+ arguments.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return mg.GetSignatureForError ();
public override void Emit (EmitContext ec)
{
+ if (mg.IsConditionallyExcluded)
+ return;
+
mg.EmitCall (ec, arguments);
}
ec.Emit (OpCodes.Pop);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (arguments != null)
+ arguments.FlowAnalysis (fc);
+ }
+
public void AddressOf (EmitContext ec, AddressOp mode)
{
EmitAddressOf (ec, mode);
{
throw new InternalErrorException ("Missing Resolve call");
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ throw new InternalErrorException ("Missing Resolve call");
+ }
public override object Accept (StructuralVisitor visitor)
{
ec.Report.Error (248, loc, "Cannot create an array with a negative size");
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ foreach (var arg in arguments)
+ arg.FlowAnalysis (fc);
+
+ if (array_data != null) {
+ foreach (var ad in array_data)
+ ad.FlowAnalysis (fc);
+ }
+ }
+
bool InitializersContainAwait ()
{
if (array_data == null)
#endregion
- public void CheckStructThisDefiniteAssignment (ResolveContext rc)
+ void CheckStructThisDefiniteAssignment (FlowAnalysisContext fc)
{
//
// It's null for all cases when we don't need to check `this'
if (variable_info == null)
return;
- if (rc.OmitStructFlowAnalysis)
+ if (fc.IsDefinitelyAssigned (variable_info))
return;
- if (!variable_info.IsAssigned (rc)) {
- rc.Report.Error (188, loc,
- "The `this' object cannot be used before all of its fields are assigned to");
- }
+ fc.Report.Error (188, loc, "The `this' object cannot be used before all of its fields are assigned to");
}
protected virtual void Error_ThisNotAvailable (ResolveContext ec)
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ CheckStructThisDefiniteAssignment (fc);
+ }
+
public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
{
if (ae == null)
protected override Expression DoResolve (ResolveContext ec)
{
ResolveBase (ec);
-
- CheckStructThisDefiniteAssignment (ec);
-
return this;
}
if (eclass == ExprClass.Unresolved)
ResolveBase (ec);
- if (variable_info != null)
- variable_info.SetAssigned (ec);
-
if (type.IsClass){
if (right_side == EmptyExpression.UnaryAddress)
ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
{
// Nothing
}
-
- public override void VerifyDefiniteAssignment (ResolveContext rc)
- {
- }
public override object Accept (StructuralVisitor visitor)
{
protected override Expression DoResolve (ResolveContext rc)
{
- var e = DoResolveName (rc, null);
-
- if (!rc.OmitStructFlowAnalysis) {
- var fe = e as FieldExpr;
- if (fe != null) {
- fe.VerifyAssignedStructField (rc, null);
- }
- }
+ var e = LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess);
+ if (e != null)
+ e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
return e;
}
public override Expression DoResolveLValue (ResolveContext rc, Expression rhs)
{
- var e = DoResolveName (rc, rhs);
-
- if (!rc.OmitStructFlowAnalysis) {
- var fe = e as FieldExpr;
- if (fe != null && fe.InstanceExpression is FieldExpr) {
- fe = (FieldExpr) fe.InstanceExpression;
- fe.VerifyAssignedStructField (rc, rhs);
- }
- }
+ var e = LookupNameExpression (rc, MemberLookupRestrictions.None);
- return e;
- }
-
- Expression DoResolveName (ResolveContext rc, Expression right_side)
- {
- Expression e = LookupNameExpression (rc, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
- if (e == null)
+ if (e is TypeExpr) {
+ e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
return null;
-
- if (right_side != null) {
- if (e is TypeExpr) {
- e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
- return null;
- }
-
- e = e.ResolveLValue (rc, right_side);
- } else {
- e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
}
+ if (e != null)
+ e = e.ResolveLValue (rc, rhs);
+
return e;
}
var sn = expr as SimpleName;
const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
- //
- // Resolve the expression with flow analysis turned off, we'll do the definite
- // assignment checks later. This is because we don't know yet what the expression
- // will resolve to - it may resolve to a FieldExpr and in this case we must do the
- // definite assignment check on the actual field and not on the whole struct.
- //
- using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
- if (sn != null) {
- expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
+ if (sn != null) {
+ expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
- //
- // Resolve expression which does have type set as we need expression type
- // with disable flow analysis as we don't know whether left side expression
- // is used as variable or type
- //
- if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
- using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- expr = expr.Resolve (rc);
- }
- } else if (expr is TypeParameterExpr) {
- expr.Error_UnexpectedKind (rc, flags, sn.Location);
- expr = null;
- }
- } else {
- expr = expr.Resolve (rc, flags);
+ //
+ // Resolve expression which does have type set as we need expression type
+ // with disable flow analysis as we don't know whether left side expression
+ // is used as variable or type
+ //
+ if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
+ expr = expr.Resolve (rc);
+ } else if (expr is TypeParameterExpr) {
+ expr.Error_UnexpectedKind (rc, flags, sn.Location);
+ expr = null;
}
+ } else {
+ expr = expr.Resolve (rc, flags);
}
if (expr == null)
if (me != null)
me.ResolveInstanceExpression (rc, null);
- //
- // Run defined assigned checks on expressions resolved with
- // disabled flow-analysis
- //
- if (sn != null) {
- var vr = expr as VariableReference;
- if (vr != null)
- vr.VerifyDefiniteAssignment (rc);
- }
-
Arguments args = new Arguments (1);
args.Add (new Argument (expr));
return new DynamicMemberBinder (Name, args, loc);
emg.SetTypeArguments (rc, targs);
}
- //
- // Run defined assigned checks on expressions resolved with
- // disabled flow-analysis
- //
- if (sn != null && !errorMode) {
- var vr = expr as VariableReference;
- if (vr != null)
- vr.VerifyDefiniteAssignment (rc);
- }
-
// TODO: it should really skip the checks bellow
return emg.Resolve (rc);
}
me.SetTypeArguments (rc, targs);
}
- //
- // Run defined assigned checks on expressions resolved with
- // disabled flow-analysis
- //
- if (sn != null && !(me is FieldExpr && TypeSpec.IsValueType (expr_type))) {
- var vr = expr as VariableReference;
- if (vr != null)
- vr.VerifyDefiniteAssignment (rc);
- }
-
return me;
}
Expr.EmitBranchable (ec, target, on_true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
using (ctx.With (BuilderContext.Options.CheckedScope, true)) {
Expr.EmitBranchable (ec, target, on_true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
UnCheckedExpr target = (UnCheckedExpr) t;
Report.Error (1742, na.Location, "An element access expression cannot use named argument");
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+ Arguments.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return Expr.GetSignatureForError ();
ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ ea.FlowAnalysis (fc);
+ }
+
//
// Load the array arguments into the stack.
//
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ // TODO: Check the order
+ base.FlowAnalysis (fc);
+ arguments.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return best_candidate.GetSignatureForError ();
ec.Emit (OpCodes.Call, method);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ source.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return TypeManager.CSharpSignature (method);
e.EmitStatement (ec);
}
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ foreach (var initializer in initializers)
+ initializer.FlowAnalysis (fc);
+ }
}
//
return instance;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ base.FlowAnalysis (fc);
+ initializers.FlowAnalysis (fc);
+ }
+
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);