X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=5a2b3615b25bef788e947fae9d719f7942fd6df6;hb=cafb63ae22a218cda3fa7b48ac4d22b5519e2747;hp=10388a677197ef988723ee8da164db59256ccb81;hpb=c09387c13d274a0b28b1ae90a577fc41761b817a;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 10388a67719..5a2b3615b25 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1281,33 +1281,17 @@ namespace Mono.CSharp { this.expr = expr; this.loc = loc; - if (target_type == TypeManager.system_void_expr) { + if (target_type == TypeManager.system_void_expr) Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); - } } public Expression TargetType { - get { - return target_type; - } + get { return target_type; } } public Expression Expr { - get { - return expr; - } - set { - expr = value; - } - } - - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) - { - expr = expr.DoResolveLValue (ec, right_side); - if (expr == null) - return null; - - return ResolveRest (ec); + get { return expr; } + set { expr = value; } } public override Expression DoResolve (EmitContext ec) @@ -1316,11 +1300,6 @@ namespace Mono.CSharp { if (expr == null) return null; - return ResolveRest (ec); - } - - Expression ResolveRest (EmitContext ec) - { TypeExpr target = target_type.ResolveAsTypeTerminal (ec, false); if (target == null) return null; @@ -1356,9 +1335,6 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - // - // This one will never happen - // throw new Exception ("Should not happen"); } } @@ -3399,7 +3375,7 @@ namespace Mono.CSharp { bool is_readonly; bool prepared; LocalTemporary temp; - + public LocalVariableReference (Block block, string name, Location l) { Block = block; @@ -3421,15 +3397,11 @@ namespace Mono.CSharp { } public VariableInfo VariableInfo { - get { - return local_info.VariableInfo; - } + get { return local_info.VariableInfo; } } public bool IsReadOnly { - get { - return is_readonly; - } + get { return is_readonly; } } public bool VerifyAssigned (EmitContext ec) @@ -3438,52 +3410,25 @@ namespace Mono.CSharp { return variable_info == null || variable_info.IsAssigned (ec, loc); } - protected Expression DoResolveBase (EmitContext ec, Expression lvalue_right_side) + void ResolveLocalInfo () { if (local_info == null) { local_info = Block.GetLocalInfo (Name); - - // is out param - if (lvalue_right_side == EmptyExpression.OutAccess) - local_info.Used = true; - is_readonly = local_info.ReadOnly; } + } + protected Expression DoResolveBase (EmitContext ec) + { type = local_info.VariableType; - VariableInfo variable_info = local_info.VariableInfo; - if (lvalue_right_side != null){ - if (is_readonly){ - if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.OutAccess) - Report.Error (1657, loc, "Cannot pass `{0}' as a ref or out argument because it is a `{1}'", - Name, local_info.GetReadOnlyContext ()); - else if (lvalue_right_side == EmptyExpression.LValueMemberAccess) - Report.Error (1654, loc, "Cannot assign to members of `{0}' because it is a `{1}'", - Name, local_info.GetReadOnlyContext ()); - else - Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", - Name, local_info.GetReadOnlyContext ()); - return null; - } - - if (variable_info != null) - variable_info.SetAssigned (ec); - } - Expression e = Block.GetConstantExpression (Name); - if (e != null) { - local_info.Used = true; - eclass = ExprClass.Value; + if (e != null) return e.Resolve (ec); - } if (!VerifyAssigned (ec)) return null; - if (lvalue_right_side == null) - local_info.Used = true; - if (ec.CurrentAnonymousMethod != null){ // // If we are referencing a variable from the external block @@ -3502,15 +3447,42 @@ namespace Mono.CSharp { return this; } - + public override Expression DoResolve (EmitContext ec) { - return DoResolveBase (ec, null); + ResolveLocalInfo (); + local_info.Used = true; + return DoResolveBase (ec); } override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { - return DoResolveBase (ec, right_side); + ResolveLocalInfo (); + + if (is_readonly) { + int code; + string msg; + if (right_side == EmptyExpression.OutAccess) { + code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberAccess) { + code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberOutAccess) { + code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'"; + } else { + code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'"; + } + Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ()); + return null; + } + + // is out param + if (right_side == EmptyExpression.OutAccess) + local_info.Used = true; + + if (VariableInfo != null) + VariableInfo.SetAssigned (ec); + + return DoResolveBase (ec); } public bool VerifyFixed () @@ -3519,7 +3491,7 @@ namespace Mono.CSharp { return true; } - public override int GetHashCode() + public override int GetHashCode () { return Name.GetHashCode (); } @@ -4005,106 +3977,47 @@ namespace Mono.CSharp { return true; } - - void Error_LValueRequired (Location loc) - { - Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); - } public bool Resolve (EmitContext ec, Location loc) { bool old_do_flow_analysis = ec.DoFlowAnalysis; ec.DoFlowAnalysis = true; - if (ArgType == AType.Ref) { - ec.InRefOutArgumentResolving = true; + // Verify that the argument is readable + if (ArgType != AType.Out) Expr = Expr.Resolve (ec); - ec.InRefOutArgumentResolving = false; - if (Expr == null) { - ec.DoFlowAnalysis = old_do_flow_analysis; - return false; - } - int errors = Report.Errors; - Expr = Expr.DoResolveLValue (ec, Expr); - if (Expr == null && errors == Report.Errors) - Error_LValueRequired (loc); - } else if (ArgType == AType.Out) { - int errors = Report.Errors; - ec.InRefOutArgumentResolving = true; - Expr = Expr.DoResolveLValue (ec, EmptyExpression.OutAccess); - ec.InRefOutArgumentResolving = false; - - if (Expr == null && errors == Report.Errors) - Error_LValueRequired (loc); - } - else - Expr = Expr.Resolve (ec); + // Verify that the argument is writeable + if (Expr != null && (ArgType == AType.Out || ArgType == AType.Ref)) + Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess, loc); ec.DoFlowAnalysis = old_do_flow_analysis; - if (Expr == null) - return false; - - if (ArgType == AType.Expression) - return true; - else { - // - // Catch errors where fields of a MarshalByRefObject are passed as ref or out - // This is only allowed for `this' - // - FieldExpr fe = Expr as FieldExpr; - if (fe != null && !fe.IsStatic){ - Expression instance = fe.InstanceExpression; - - if (instance.GetType () != typeof (This)){ - if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){ - Report.SymbolRelatedToPreviousError (fe.InstanceExpression.Type); - Report.Warning (197, 1, loc, - "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class", - fe.GetSignatureForError ()); - return false; - } - } - } - } - - return true; + return Expr != null; } public void Emit (EmitContext ec) { - // - // Ref and Out parameters need to have their addresses taken. + if (ArgType != AType.Ref && ArgType != AType.Out) { + Expr.Emit (ec); + return; + } + + AddressOp mode = AddressOp.Store; + if (ArgType == AType.Ref) + mode |= AddressOp.Load; + + IMemoryLocation ml = (IMemoryLocation) Expr; + ParameterReference pr = ml as ParameterReference; + // // ParameterReferences might already be references, so we want // to pass just the value // - if (ArgType == AType.Ref || ArgType == AType.Out){ - AddressOp mode = AddressOp.Store; - - if (ArgType == AType.Ref) - mode |= AddressOp.Load; - - if (Expr is ParameterReference){ - ParameterReference pr = (ParameterReference) Expr; - - if (pr.IsRef) - pr.EmitLoad (ec); - else { - - pr.AddressOf (ec, mode); - } - } else { - if (Expr is IMemoryLocation) - ((IMemoryLocation) Expr).AddressOf (ec, mode); - else { - Error_LValueRequired (Expr.Location); - return; - } - } - } else - Expr.Emit (ec); + if (pr != null && pr.IsRef) + pr.EmitLoad (ec); + else + ml.AddressOf (ec, mode); } } @@ -4879,85 +4792,54 @@ namespace Mono.CSharp { Location loc) { ParameterData pd = TypeManager.GetParameterData (method); - int pd_count = pd.Count; - - for (int j = 0; j < arg_count; j++) { + int j; + for (j = 0; j < arg_count; j++) { Argument a = (Argument) Arguments [j]; Expression a_expr = a.Expr; Type parameter_type = pd.ParameterType (j); Parameter.Modifier pm = pd.ParameterModifier (j); - - if (pm == Parameter.Modifier.PARAMS){ - if ((pm & ~Parameter.Modifier.PARAMS) != a.Modifier) { - if (!may_fail) - Error_InvalidArguments (loc, j, method, delegate_type, a, pd); - return false; - } + Parameter.Modifier am = a.Modifier; + if (pm == Parameter.Modifier.ARGLIST) { + if (!(a.Expr is Arglist)) + break; + continue; + } + + if (pm == Parameter.Modifier.PARAMS) { + pm = Parameter.Modifier.NONE; if (chose_params_expanded) parameter_type = TypeManager.GetElementType (parameter_type); - } else if (pm == Parameter.Modifier.ARGLIST) { - if (!(a.Expr is Arglist)) { - if (!may_fail) - Error_InvalidArguments (loc, j, method, delegate_type, a, pd); - return false; - } - continue; - } else { - // - // Check modifiers - // - if (pd.ParameterModifier (j) != a.Modifier){ - if (!may_fail) - Error_InvalidArguments (loc, j, method, delegate_type, a, pd); - return false; - } } - // - // Check Type - // - if (!a.Type.Equals (parameter_type)){ - Expression conv; - - conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc); + if (pm != am) + break; + + if (!a.Type.Equals (parameter_type)) { + if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF) + break; + + Expression conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc); + if (conv == null) + break; - if (conv == null) { - if (!may_fail) - Error_InvalidArguments (loc, j, method, delegate_type, a, pd); - return false; - } - - // // Update the argument with the implicit conversion - // if (a_expr != conv) a.Expr = conv; } - if (parameter_type.IsPointer){ - if (!ec.InUnsafe){ - UnsafeError (loc); - return false; - } - } - - Parameter.Modifier a_mod = a.Modifier & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); - Parameter.Modifier p_mod = pd.ParameterModifier (j) & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); - - if (a_mod != p_mod && - pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) { - if (!may_fail) { - Invocation.Error_InvalidArguments (loc, j, method, null, a, pd); - } - + if (parameter_type.IsPointer && !ec.InUnsafe) { + UnsafeError (loc); return false; } } - return true; + if (j == arg_count) + return true; + + if (!may_fail) + Error_InvalidArguments (loc, j, method, delegate_type, (Argument) Arguments [j], pd); + return false; } private bool resolved = false; @@ -5056,7 +4938,7 @@ namespace Mono.CSharp { } if (mg.InstanceExpression != null) - mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); + mg.InstanceExpression.CheckMarshalByRefAccess (); eclass = ExprClass.Value; this.method = method; @@ -6523,24 +6405,26 @@ namespace Mono.CSharp { if (array_data == null) { Constant c = (Constant)((Argument)arguments [0]).Expr; if (c.IsDefaultValue) { - value = new object [0]; + value = Array.CreateInstance (array_element_type, 0); return true; } // Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); return base.GetAttributableValue (null, out value); } - object [] ret = new object [array_data.Count]; + Array ret = Array.CreateInstance (array_element_type, array_data.Count); + object element_value; for (int i = 0; i < ret.Length; ++i) { Expression e = (Expression)array_data [i]; - if (e == null) // Is null when initializer is optimized out + if (e == null) // Is null when initializer is optimized away e = (Expression)initializers [i]; - if (!e.GetAttributableValue (array_element_type, out ret [i])) { + if (!e.GetAttributableValue (array_element_type, out element_value)) { value = null; return false; } + ret.SetValue (element_value, i); } value = ret; return true; @@ -7975,7 +7859,7 @@ namespace Mono.CSharp { return null; } - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); + instance_expr.CheckMarshalByRefAccess (); eclass = ExprClass.IndexerAccess; return this; @@ -7990,7 +7874,7 @@ namespace Mono.CSharp { } // if the indexer returns a value type, and we try to set a field in it - if (right_side == EmptyExpression.LValueMemberAccess) { + if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) { Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", GetSignatureForError ()); return null; @@ -8055,7 +7939,7 @@ namespace Mono.CSharp { } } - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); + instance_expr.CheckMarshalByRefAccess (); eclass = ExprClass.IndexerAccess; return this; @@ -8255,6 +8139,7 @@ namespace Mono.CSharp { public static readonly EmptyExpression OutAccess = new EmptyExpression (); public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (); + public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression (); static EmptyExpression temp = new EmptyExpression (); public static EmptyExpression Grab ()