X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=5a2b3615b25bef788e947fae9d719f7942fd6df6;hb=cafb63ae22a218cda3fa7b48ac4d22b5519e2747;hp=0a86f9ef0e4ef3dbba7335df95bb45c32929357d;hpb=cc56a2d3c3d3fc821c2c7abed567899d244492c4;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 0a86f9ef0e4..5a2b3615b25 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -693,7 +693,7 @@ namespace Mono.CSharp { Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temporary = new LocalTemporary (ec, expr.Type); + temporary = new LocalTemporary (expr.Type); temporary.Store (ec); } } @@ -710,7 +710,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temporary = new LocalTemporary (ec, expr.Type); + temporary = new LocalTemporary (expr.Type); temporary.Store (ec); } @@ -990,7 +990,6 @@ namespace Mono.CSharp { this.is_expr = is_expr; ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true); } - public override void Emit (EmitContext ec) { @@ -1187,7 +1186,7 @@ namespace Mono.CSharp { } return this; - } + } } /// @@ -1255,9 +1254,9 @@ namespace Mono.CSharp { return null; } - public override bool GetAttributableValue (out object value) + public override bool GetAttributableValue (Type valueType, out object value) { - return expr.GetAttributableValue (out value); + return expr.GetAttributableValue (valueType, out value); } } @@ -1282,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) @@ -1317,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; @@ -1357,9 +1335,6 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - // - // This one will never happen - // throw new Exception ("Should not happen"); } } @@ -1519,7 +1494,7 @@ namespace Mono.CSharp { + "'"); } - bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions) + static bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions) { if ((l == t) || (r == t)) return true; @@ -1589,7 +1564,7 @@ namespace Mono.CSharp { if (ll >= 0) right = new ULongConstant ((ulong) ll, right.Location); } else { - e = Convert.ImplicitNumericConversion (ec, right, l); + e = Convert.ImplicitNumericConversion (right, l); if (e != null) right = e; } @@ -1606,7 +1581,7 @@ namespace Mono.CSharp { if (ll > 0) left = new ULongConstant ((ulong) ll, right.Location); } else { - e = Convert.ImplicitNumericConversion (ec, left, r); + e = Convert.ImplicitNumericConversion (left, r); if (e != null) left = e; } @@ -1971,9 +1946,9 @@ namespace Mono.CSharp { // Also, a standard conversion must exist from either one // bool left_to_right = - Convert.ImplicitStandardConversionExists (ec, left, r); + Convert.ImplicitStandardConversionExists (left, r); bool right_to_left = !left_to_right && - Convert.ImplicitStandardConversionExists (ec, right, l); + Convert.ImplicitStandardConversionExists (right, l); if (!left_to_right && !right_to_left) { Error_OperatorCannotBeApplied (); @@ -2029,7 +2004,7 @@ namespace Mono.CSharp { // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >= // if (oper == Operator.Addition || oper == Operator.Subtraction) { - if (l.IsSubclassOf (TypeManager.delegate_type)){ + if (TypeManager.IsDelegateType (l)){ if (((right.eclass == ExprClass.MethodGroup) || (r == TypeManager.anonymous_method_type))){ if ((RootContext.Version != LanguageVersion.ISO_1)){ @@ -2040,15 +2015,15 @@ namespace Mono.CSharp { r = right.Type; } } - - if (r.IsSubclassOf (TypeManager.delegate_type)){ + + if (TypeManager.IsDelegateType (r)){ MethodInfo method; ArrayList args = new ArrayList (2); - + args = new ArrayList (2); args.Add (new Argument (left, Argument.AType.Expression)); args.Add (new Argument (right, Argument.AType.Expression)); - + if (oper == Operator.Addition) method = TypeManager.delegate_combine_delegate_delegate; else @@ -2058,11 +2033,11 @@ namespace Mono.CSharp { Error_OperatorCannotBeApplied (); return null; } - + return new BinaryDelegate (l, method, args); } } - + // // Pointer arithmetic: // @@ -2286,7 +2261,7 @@ namespace Mono.CSharp { return this; } - Constant EnumLiftUp (EmitContext ec, Constant left, Constant right) + Constant EnumLiftUp (Constant left, Constant right) { switch (oper) { case Operator.BitwiseOr: @@ -2363,11 +2338,11 @@ namespace Mono.CSharp { // The conversion rules are ignored in enum context but why if (!ec.InEnumContext && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) { - left = lc = EnumLiftUp (ec, lc, rc); + left = lc = EnumLiftUp (lc, rc); if (lc == null) return null; - right = rc = EnumLiftUp (ec, rc, lc); + right = rc = EnumLiftUp (rc, lc); if (rc == null) return null; } @@ -2925,11 +2900,21 @@ namespace Mono.CSharp { // // Constant folding // - if (operand is StringConstant && operands.Count != 0) { - StringConstant last_operand = operands [operands.Count - 1] as StringConstant; - if (last_operand != null) { - operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value, last_operand.Location); - return; + StringConstant sc = operand as StringConstant; + if (sc != null) { +// TODO: it will be better to do this silently as an optimalization +// int i = 0; +// string s = "" + i; +// because this code has poor performace +// if (sc.Value.Length == 0) +// Report.Warning (-300, 3, Location, "Appending an empty string has no effect. Did you intend to append a space string?"); + + if (operands.Count != 0) { + StringConstant last_operand = operands [operands.Count - 1] as StringConstant; + if (last_operand != null) { + operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value, last_operand.Location); + return; + } } } @@ -3108,7 +3093,7 @@ namespace Mono.CSharp { return null; } - left_temp = new LocalTemporary (ec, type); + left_temp = new LocalTemporary (type); ArrayList arguments = new ArrayList (); arguments.Add (new Argument (left_temp, Argument.AType.Expression)); @@ -3390,7 +3375,7 @@ namespace Mono.CSharp { bool is_readonly; bool prepared; LocalTemporary temp; - + public LocalVariableReference (Block block, string name, Location l) { Block = block; @@ -3412,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) @@ -3429,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 @@ -3493,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 () @@ -3510,7 +3491,7 @@ namespace Mono.CSharp { return true; } - public override int GetHashCode() + public override int GetHashCode () { return Name.GetHashCode (); } @@ -3550,7 +3531,7 @@ namespace Mono.CSharp { if (leave_copy){ ec.ig.Emit (OpCodes.Dup); if (local_info.FieldBuilder != null){ - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } } @@ -3583,7 +3564,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy){ ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } ig.Emit (OpCodes.Stfld, local_info.FieldBuilder); @@ -3688,7 +3669,7 @@ namespace Mono.CSharp { ec.CurrentBranching.SetAssigned (vi); } - public void SetFieldAssigned (EmitContext ec, string field_name) + public void SetFieldAssigned (EmitContext ec, string field_name) { if (is_out && ec.DoFlowAnalysis) ec.CurrentBranching.SetFieldAssigned (vi, field_name); @@ -3846,7 +3827,7 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Dup); if (is_ref) { - temp = new LocalTemporary (ec, type); + temp = new LocalTemporary (type); temp.Store (ec); } } @@ -3878,7 +3859,7 @@ namespace Mono.CSharp { if (is_ref) { if (leave_copy) { - temp = new LocalTemporary (ec, type); + temp = new LocalTemporary (type); temp.Store (ec); } @@ -3986,7 +3967,7 @@ namespace Mono.CSharp { TypeManager.CSharpName (a.Expr.Type); } - public bool ResolveMethodGroup (EmitContext ec, Location loc) + public bool ResolveMethodGroup (EmitContext ec) { // FIXME: csc doesn't report any error if you try to use `ref' or // `out' in a delegate creation expression. @@ -3996,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); } } @@ -4135,7 +4057,7 @@ namespace Mono.CSharp { /// q if a->q is better, /// null if neither is better /// - static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc) + static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q) { Type argument_type = a.Type; Expression argument_expr = a.Expr; @@ -4230,13 +4152,13 @@ namespace Mono.CSharp { /// and the current best match /// /// - /// Returns an integer indicating : + /// Returns a boolean indicating : /// false if candidate ain't better - /// true if candidate is better than the current best match + /// true if candidate is better than the current best match /// static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count, MethodBase candidate, bool candidate_params, - MethodBase best, bool best_params, Location loc) + MethodBase best, bool best_params) { ParameterData candidate_pd = TypeManager.GetParameterData (candidate); ParameterData best_pd = TypeManager.GetParameterData (best); @@ -4261,7 +4183,7 @@ namespace Mono.CSharp { continue; same = false; - Type better = BetterConversion (ec, a, ct, bt, loc); + Type better = BetterConversion (ec, a, ct, bt); // for each argument, the conversion to 'ct' should be no worse than // the conversion to 'bt'. @@ -4528,7 +4450,7 @@ namespace Mono.CSharp { static internal bool IsAncestralType (Type first_type, Type second_type) { return first_type != second_type && - (second_type.IsSubclassOf (first_type) || + (TypeManager.IsSubclassOf (second_type, first_type) || TypeManager.ImplementsInterface (second_type, first_type)); } @@ -4549,7 +4471,7 @@ namespace Mono.CSharp { /// /// public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me, - ArrayList Arguments, bool may_fail, + ArrayList Arguments, bool may_fail, Location loc) { MethodBase method = null; @@ -4758,7 +4680,7 @@ namespace Mono.CSharp { if (BetterFunction (ec, Arguments, arg_count, candidate, cand_params, - method, method_params, loc)) { + method, method_params)) { method = candidate; method_params = cand_params; } @@ -4777,8 +4699,7 @@ namespace Mono.CSharp { bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); if (!BetterFunction (ec, Arguments, arg_count, method, method_params, - candidate, cand_params, - loc)) { + candidate, cand_params)) { Report.SymbolRelatedToPreviousError (candidate); ambiguous = candidate; } @@ -4816,11 +4737,13 @@ namespace Mono.CSharp { method_params, null, may_fail, loc)) return null; - if (method != null) { - IMethodData data = TypeManager.GetMethod (method); - if (data != null) - data.SetMemberIsUsed (); - } + if (method == null) + return null; + + IMethodData data = TypeManager.GetMethod (method); + if (data != null) + data.SetMemberIsUsed (); + return method; } @@ -4869,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; @@ -5046,7 +4938,7 @@ namespace Mono.CSharp { } if (mg.InstanceExpression != null) - mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); + mg.InstanceExpression.CheckMarshalByRefAccess (); eclass = ExprClass.Value; this.method = method; @@ -5156,7 +5048,7 @@ namespace Mono.CSharp { a.Emit (ec); if (dup_args) { ec.ig.Emit (OpCodes.Dup); - (temps [i] = new LocalTemporary (ec, a.Type)).Store (ec); + (temps [i] = new LocalTemporary (a.Type)).Store (ec); } } @@ -5177,8 +5069,7 @@ namespace Mono.CSharp { } } - static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb, - ArrayList arguments) + static Type[] GetVarargsTypes (MethodBase mb, ArrayList arguments) { ParameterData pd = TypeManager.GetParameterData (mb); @@ -5278,7 +5169,6 @@ namespace Mono.CSharp { if (oa != null) AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc); - oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType); if (oa != null) { AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc); @@ -5297,13 +5187,16 @@ namespace Mono.CSharp { this_call = instance_expr is This; if (decl_type.IsValueType || (!this_call && instance_expr.Type.IsValueType)) struct_call = true; - + + // + // If this is ourselves, push "this" + // if (!omit_args) { Type t = null; // // Push the instance expression // - if (instance_expr.Type.IsValueType) { + if (TypeManager.IsValueType (instance_expr.Type)) { // // Special case: calls to a function declared in a // reference-type with a value-type argument need @@ -5320,7 +5213,7 @@ namespace Mono.CSharp { ((IMemoryLocation)instance_expr). AddressOf (ec, AddressOp.LoadStore); } else { - LocalTemporary temp = new LocalTemporary (ec, instance_expr.Type); + LocalTemporary temp = new LocalTemporary (instance_expr.Type); instance_expr.Emit (ec); temp.Store (ec); temp.AddressOf (ec, AddressOp.Load); @@ -5342,7 +5235,7 @@ namespace Mono.CSharp { if (dup_args) { ig.Emit (OpCodes.Dup); if (Arguments != null && Arguments.Count != 0) { - this_arg = new LocalTemporary (ec, t); + this_arg = new LocalTemporary (t); this_arg.Store (ec); } } @@ -5359,7 +5252,7 @@ namespace Mono.CSharp { call_op = OpCodes.Callvirt; if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { - Type[] varargs_types = GetVarargsTypes (ec, method, Arguments); + Type[] varargs_types = GetVarargsTypes (method, Arguments); ig.EmitCall (call_op, (MethodInfo) method, varargs_types); return; } @@ -5759,7 +5652,7 @@ namespace Mono.CSharp { // bool DoEmit (EmitContext ec, bool need_value_on_stack) { - bool is_value_type = type.IsValueType; + bool is_value_type = TypeManager.IsValueType (type); ILGenerator ig = ec.ig; if (is_value_type){ @@ -5769,7 +5662,7 @@ namespace Mono.CSharp { // We need to create a new LocalTemporary each time since // you can't share LocalBuilders among ILGeneators. if (!value_target_set) - value_target = new LocalTemporary (ec, type); + value_target = new LocalTemporary (type); ml = (IMemoryLocation) value_target; ml.AddressOf (ec, AddressOp.Store); @@ -5818,7 +5711,7 @@ namespace Mono.CSharp { } if (!value_target_set) - value_target = new LocalTemporary (ec, type); + value_target = new LocalTemporary (type); IMemoryLocation ml = (IMemoryLocation) value_target; ml.AddressOf (ec, AddressOp.Store); @@ -5870,15 +5763,10 @@ namespace Mono.CSharp { ArrayList array_data; - Hashtable bounds; - - // - // The number of array initializers that we can handle - // via the InitializeArray method - through EmitStaticInitializers - // - int num_automatic_initializers; + IDictionary bounds; - const int max_automatic_initializers = 6; + // The number of constants in array initializers + int const_initializers_count; public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l) { @@ -5928,7 +5816,7 @@ namespace Mono.CSharp { Error (178, "Invalid rank specifier: expected `,' or `]'"); } - public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims) + bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims) { if (specified_dims) { Argument a = (Argument) arguments [idx]; @@ -5970,7 +5858,7 @@ namespace Mono.CSharp { Error_IncorrectArrayInitializer (); return false; } - if (specified_dims && (idx + 1 >= arguments.Count)){ + if (idx + 1 >= dimensions){ Error (623, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); return false; } @@ -5986,38 +5874,37 @@ namespace Mono.CSharp { Expression tmp = (Expression) o; tmp = tmp.Resolve (ec); - probe [i] = tmp; if (tmp == null) return false; - // Console.WriteLine ("I got: " + tmp); - // Handle initialization from vars, fields etc. - Expression conv = Convert.ImplicitConversionRequired ( ec, tmp, underlying_type, loc); if (conv == null) return false; + + // Initializers with the default values can be ignored + Constant c = tmp as Constant; + if (c != null) { + if (c.IsDefaultInitializer (array_element_type)) { + conv = null; + } + else { + ++const_initializers_count; + } + } else { + // Used to invalidate static initializer + const_initializers_count = int.MinValue; + } - if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) { - // These are subclasses of Constant that can appear as elements of an - // array that cannot be statically initialized (with num_automatic_initializers - // > max_automatic_initializers), so num_automatic_initializers should be left as zero. - array_data.Add (conv); - } else if (conv is Constant) { - // These are the types of Constant that can appear in arrays that can be - // statically allocated. - array_data.Add (conv); - num_automatic_initializers++; - } else - array_data.Add (conv); + array_data.Add (conv); } } return true; } - public void UpdateIndices (EmitContext ec) + public void UpdateIndices () { int i = 0; for (ArrayList probe = initializers; probe != null;) { @@ -6034,13 +5921,13 @@ namespace Mono.CSharp { arguments.Add (new Argument (e, Argument.AType.Expression)); bounds [i++] = probe.Count; - probe = null; + return; } } } - public bool ValidateInitializers (EmitContext ec, Type array_type) + bool ResolveInitializers (EmitContext ec) { if (initializers == null) { return !expect_initializers; @@ -6054,25 +5941,24 @@ namespace Mono.CSharp { // will need to store them in the byte blob later // array_data = new ArrayList (); - bounds = new Hashtable (); + bounds = new System.Collections.Specialized.HybridDictionary (); - if (arguments != null) { + if (arguments != null) return CheckIndices (ec, initializers, 0, true); - } else { - arguments = new ArrayList (); - if (!CheckIndices (ec, initializers, 0, false)) - return false; + arguments = new ArrayList (); + + if (!CheckIndices (ec, initializers, 0, false)) + return false; - UpdateIndices (ec); + UpdateIndices (); - if (arguments.Count != dimensions) { - Error_IncorrectArrayInitializer (); - return false; - } - - return true; + if (arguments.Count != dimensions) { + Error_IncorrectArrayInitializer (); + return false; } + + return true; } // @@ -6111,18 +5997,26 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - int arg_count; + if (type != null) + return this; if (!LookupType (ec)) return null; + array_element_type = TypeManager.GetElementType (type); + if (array_element_type.IsAbstract && array_element_type.IsSealed) { + Report.Error (719, loc, "`{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type)); + return null; + } + // // First step is to validate the initializers and fill // in any missing bits // - if (!ValidateInitializers (ec, type)) + if (!ResolveInitializers (ec)) return null; + int arg_count; if (arguments == null) arg_count = 0; else { @@ -6139,13 +6033,6 @@ namespace Mono.CSharp { } } - array_element_type = TypeManager.GetElementType (type); - - if (array_element_type.IsAbstract && array_element_type.IsSealed) { - Report.Error (719, loc, "`{0}': array elements cannot be of static type", TypeManager.CSharpName (array_element_type)); - return null; - } - if (arg_count == 1) { is_one_dimensional = true; eclass = ExprClass.Value; @@ -6212,7 +6099,7 @@ namespace Mono.CSharp { } } - public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc) + byte [] MakeByteBlob () { int factor; byte [] data; @@ -6228,7 +6115,7 @@ namespace Mono.CSharp { data = new byte [(count * factor + 4) & ~3]; int idx = 0; - + for (int i = 0; i < count; ++i) { object v = array_data [i]; @@ -6367,7 +6254,7 @@ namespace Mono.CSharp { FieldBuilder fb; ILGenerator ig = ec.ig; - byte [] data = MakeByteBlob (array_data, underlying_type, loc); + byte [] data = MakeByteBlob (); fb = RootContext.MakeStaticData (data); @@ -6388,87 +6275,67 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; int dims = bounds.Count; int [] current_pos = new int [dims]; - int top = array_data.Count; MethodInfo set = null; if (dims != 1){ - Type [] args; - ModuleBuilder mb = null; - mb = CodeGen.Module.Builder; - args = new Type [dims + 1]; + Type [] args = new Type [dims + 1]; - int j; - for (j = 0; j < dims; j++) + for (int j = 0; j < dims; j++) args [j] = TypeManager.int32_type; - - args [j] = array_element_type; + args [dims] = array_element_type; - set = mb.GetArrayMethod ( + set = CodeGen.Module.Builder.GetArrayMethod ( type, "Set", CallingConventions.HasThis | CallingConventions.Standard, TypeManager.void_type, args); } - - for (int i = 0; i < top; i++){ - Expression e = null; + for (int i = 0; i < array_data.Count; i++){ - if (array_data [i] is Expression) - e = (Expression) array_data [i]; + Expression e = (Expression)array_data [i]; if (e != null) { - // - // Basically we do this for string literals and - // other non-literal expressions - // - if (e is EnumConstant){ - e = ((EnumConstant) e).Child; - } - - if (e is StringConstant || e is DecimalConstant || !(e is Constant) || - num_automatic_initializers <= max_automatic_initializers) { - Type etype = e.Type; + Type etype = e.Type; - ig.Emit (OpCodes.Dup); + ig.Emit (OpCodes.Dup); - for (int idx = 0; idx < dims; idx++) - IntConstant.EmitInt (ig, current_pos [idx]); + for (int idx = 0; idx < dims; idx++) + IntConstant.EmitInt (ig, current_pos [idx]); - // - // If we are dealing with a struct, get the - // address of it, so we can store it. - // - if ((dims == 1) && - TypeManager.IsValueType (etype) && - (!TypeManager.IsBuiltinOrEnum (etype) || - etype == TypeManager.decimal_type)) { - if (e is New){ - New n = (New) e; - - // - // Let new know that we are providing - // the address where to store the results - // - n.DisableTemporaryValueType (); - } + // + // If we are dealing with a struct, get the + // address of it, so we can store it. + // + if ((dims == 1) && + TypeManager.IsValueType (etype) && + (!TypeManager.IsBuiltinOrEnum (etype) || + etype == TypeManager.decimal_type)) { + if (e is New){ + New n = (New) e; - ig.Emit (OpCodes.Ldelema, etype); + // + // Let new know that we are providing + // the address where to store the results + // + n.DisableTemporaryValueType (); } - e.Emit (ec); + ig.Emit (OpCodes.Ldelema, etype); + } + + e.Emit (ec); - if (dims == 1) { - bool is_stobj; - OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj); - if (is_stobj) - ig.Emit (OpCodes.Stobj, etype); - else - ig.Emit (op); - } else - ig.Emit (OpCodes.Call, set); + if (dims == 1) { + bool is_stobj; + OpCode op = ArrayAccess.GetStoreOpcode (etype, out is_stobj); + if (is_stobj) + ig.Emit (OpCodes.Stobj, etype); + else + ig.Emit (op); + } else + ig.Emit (OpCodes.Call, set); - } } // @@ -6512,53 +6379,75 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Newobj, (MethodInfo) new_method); } - if (initializers != null){ - // - // FIXME: Set this variable correctly. - // - bool dynamic_initializers = true; + if (initializers == null) + return; - // This will never be true for array types that cannot be statically - // initialized. num_automatic_initializers will always be zero. See - // CheckIndices. - if (num_automatic_initializers > max_automatic_initializers) - EmitStaticInitializers (ec); - - if (dynamic_initializers) - EmitDynamicInitializers (ec); + // This is a treshold for static initializers + // I tried to make more accurate but it seems to me that Array.Initialize is + // always slower (managed -> unmanaged switch?) + const int max_automatic_initializers = 200; + + if (const_initializers_count > max_automatic_initializers && TypeManager.IsPrimitiveType (array_element_type)) { + EmitStaticInitializers (ec); + return; } + + EmitDynamicInitializers (ec); } - public override bool GetAttributableValue (out object value) + public override bool GetAttributableValue (Type valueType, out object value) { if (!is_one_dimensional){ // Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); - return base.GetAttributableValue (out value); + return base.GetAttributableValue (null, out value); } 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 (out value); + 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) { - if (!((Expression)array_data [i]).GetAttributableValue (out ret [i])) { + Expression e = (Expression)array_data [i]; + if (e == null) // Is null when initializer is optimized away + e = (Expression)initializers [i]; + + if (!e.GetAttributableValue (array_element_type, out element_value)) { value = null; return false; } + ret.SetValue (element_value, i); } value = ret; return true; } } + public sealed class CompilerGeneratedThis : This + { + public static This Instance = new CompilerGeneratedThis (); + + private CompilerGeneratedThis () + : base (Location.Null) + { + } + + public override Expression DoResolve (EmitContext ec) + { + eclass = ExprClass.Variable; + type = ec.ContainerType; + return this; + } + } + /// /// Represents the `this' construct /// @@ -6658,7 +6547,7 @@ namespace Mono.CSharp { LocalTemporary t = null; if (leave_copy) { - t = new LocalTemporary (ec, type); + t = new LocalTemporary (type); ec.ig.Emit (OpCodes.Dup); t.Store (ec); } @@ -6720,19 +6609,13 @@ namespace Mono.CSharp { this.loc = loc; } - public bool ResolveBase (EmitContext ec) + public override Expression DoResolve (EmitContext ec) { eclass = ExprClass.Variable; type = TypeManager.runtime_argument_handle_type; - return true; - } - public override Expression DoResolve (EmitContext ec) - { - if (!ResolveBase (ec)) - return null; - - if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) { + if (ec.IsFieldInitializer || !ec.CurrentBlock.Toplevel.HasVarargs) + { Error (190, "The __arglist construct is valid only within " + "a variable argument method."); return null; @@ -6856,8 +6739,12 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); } - public override bool GetAttributableValue (out object value) + public override bool GetAttributableValue (Type valueType, out object value) { + if (valueType == TypeManager.object_type) { + value = (object)typearg; + return true; + } value = typearg; return true; } @@ -6951,7 +6838,7 @@ namespace Mono.CSharp { public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { if (alias == "global") - return new MemberAccess (RootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent); + return new MemberAccess (RootNamespace.Global, identifier).ResolveAsTypeStep (ec, silent); int errors = Report.Errors; FullNamedExpression fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias); @@ -6965,7 +6852,7 @@ namespace Mono.CSharp { Report.Error (431, loc, "`{0}' cannot be used with '::' since it denotes a type", alias); return null; } - return new MemberAccess (fne, identifier, loc).ResolveAsTypeStep (ec, silent); + return new MemberAccess (fne, identifier).ResolveAsTypeStep (ec, silent); } public override Expression DoResolve (EmitContext ec) @@ -6983,7 +6870,7 @@ namespace Mono.CSharp { } } - Expression retval = new MemberAccess (fne, identifier, loc).DoResolve (ec); + Expression retval = new MemberAccess (fne, identifier).DoResolve (ec); if (retval == null) return null; @@ -7024,8 +6911,7 @@ namespace Mono.CSharp { public readonly string Identifier; Expression expr; - // TODO: Location can be removed - public MemberAccess (Expression expr, string id, Location l) + public MemberAccess (Expression expr, string id) { this.expr = expr; Identifier = id; @@ -7669,7 +7555,7 @@ namespace Mono.CSharp { if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } } @@ -7692,7 +7578,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } StoreFromPtr (ec.ig, t); @@ -7719,7 +7605,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } @@ -7736,7 +7622,7 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, this.type); + temp = new LocalTemporary (this.type); temp.Store (ec); } @@ -7850,7 +7736,7 @@ namespace Mono.CSharp { BindingFlags.DeclaredOnly, p_name, null); } - static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) + static public Indexers GetIndexersForType (Type caller_type, Type lookup_type) { Indexers ix = empty; @@ -7926,7 +7812,7 @@ namespace Mono.CSharp { bool found_any = false, found_any_getters = false; Type lookup_type = indexer_type; - Indexers ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc); + Indexers ilist = Indexers.GetIndexersForType (current_type, lookup_type); if (ilist.Properties != null) { found_any = true; foreach (Indexers.Indexer ix in ilist.Properties) { @@ -7973,7 +7859,7 @@ namespace Mono.CSharp { return null; } - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); + instance_expr.CheckMarshalByRefAccess (); eclass = ExprClass.IndexerAccess; return this; @@ -7988,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; @@ -8000,7 +7886,7 @@ namespace Mono.CSharp { bool found_any = false, found_any_setters = false; - Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc); + Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type); if (ilist.Properties != null) { found_any = true; foreach (Indexers.Indexer ix in ilist.Properties) { @@ -8053,7 +7939,7 @@ namespace Mono.CSharp { } } - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); + instance_expr.CheckMarshalByRefAccess (); eclass = ExprClass.IndexerAccess; return this; @@ -8067,7 +7953,7 @@ namespace Mono.CSharp { Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc, prepared, false); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } } @@ -8086,11 +7972,11 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); temp.Store (ec); } } else if (leave_copy) { - temp = new LocalTemporary (ec, Type); + temp = new LocalTemporary (Type); source.Emit (ec); temp.Store (ec); a.Expr = temp; @@ -8253,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 () @@ -8370,7 +8257,7 @@ namespace Mono.CSharp { loc = l; } - public override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false); if (lexpr == null)