X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fexpression.cs;h=889d3eba69703e357e38bd15c0fb18a984ce0a12;hb=dd866d68820e0f66046256bb5d3f84e3988a8be0;hp=934349c7cae8311f32029a71bd05649f5eab79a7;hpb=d2bf56daae300488f2c9cbdcedc77f75900234a0;p=mono.git diff --git a/mcs/gmcs/expression.cs b/mcs/gmcs/expression.cs index 934349c7cae..889d3eba697 100755 --- a/mcs/gmcs/expression.cs +++ b/mcs/gmcs/expression.cs @@ -430,6 +430,11 @@ namespace Mono.CSharp { return null; } + if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) { + Error (213, "You can not fix an already fixed expression"); + return null; + } + // According to the specs, a variable is considered definitely assigned if you take // its address. if ((variable != null) && (variable.VariableInfo != null)) @@ -563,6 +568,16 @@ namespace Mono.CSharp { return ResolveOperator (ec); } + public override Expression DoResolveLValue (EmitContext ec, Expression right) + { + if (Oper == Operator.Indirection) + return base.DoResolveLValue (ec, right); + + Error (131, "The left-hand side of an assignment must be a " + + "variable, property or indexer"); + return null; + } + public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; @@ -972,6 +987,13 @@ namespace Mono.CSharp { ia.CacheTemporaries (ec); + // + // NOTE: We should probably handle three cases: + // + // * method invocation required. + // * direct stack manipulation possible + // * the object requires an "instance" field + // if (temp_storage == null){ // // Temporary improvement: if we are dealing with something that does @@ -1097,6 +1119,8 @@ namespace Mono.CSharp { if (probe_type == null) return null; + CheckObsoleteAttribute (probe_type); + expr = expr.Resolve (ec); if (expr == null) return null; @@ -1833,6 +1857,8 @@ namespace Mono.CSharp { if (type == null) return null; + CheckObsoleteAttribute (type); + eclass = ExprClass.Value; if (expr is Constant){ @@ -1842,6 +1868,10 @@ namespace Mono.CSharp { return e; } + if (type.IsPointer && !ec.InUnsafe) { + UnsafeError (loc); + return null; + } expr = Convert.ExplicitConversion (ec, expr, type, loc); return expr; } @@ -2077,7 +2107,7 @@ namespace Mono.CSharp { } else if (right is LongConstant){ long ll = ((LongConstant) right).Value; - if (ll > 0) + if (ll >= 0) right = new ULongConstant ((ulong) ll); } else { e = Convert.ImplicitNumericConversion (ec, right, l, loc); @@ -2279,7 +2309,7 @@ namespace Mono.CSharp { bool overload_failed = false; // - // Special cases: string comapred to null + // Special cases: string or type parameter comapred to null // if (oper == Operator.Equality || oper == Operator.Inequality){ if ((l == TypeManager.string_type && (right is NullLiteral)) || @@ -2288,6 +2318,35 @@ namespace Mono.CSharp { return this; } + + if (l.IsGenericParameter && (right is NullLiteral)) { + if (l.BaseType == TypeManager.value_type) { + Error_OperatorCannotBeApplied (); + return null; + } + + left = new BoxedCast (left); + Type = TypeManager.bool_type; + return this; + } + + if (r.IsGenericParameter && (left is NullLiteral)) { + if (r.BaseType == TypeManager.value_type) { + Error_OperatorCannotBeApplied (); + return null; + } + + right = new BoxedCast (right); + Type = TypeManager.bool_type; + return this; + } + + // IntPtr equality + if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) { + Type = TypeManager.bool_type; + + return this; + } } // @@ -2337,93 +2396,35 @@ namespace Mono.CSharp { // If any of the arguments is a string, cast to string // - if (l == TypeManager.string_type){ - MethodBase method; - - if (r == TypeManager.void_type) { - Error_OperatorCannotBeApplied (); - return null; - } - - if (r == TypeManager.string_type){ - if (left is Constant && right is Constant){ - StringConstant ls = (StringConstant) left; - StringConstant rs = (StringConstant) right; - - return new StringConstant ( - ls.Value + rs.Value); - } - - if (left is BinaryMethod){ - BinaryMethod b = (BinaryMethod) left; - - // - // Call String.Concat (string, string, string) or - // String.Concat (string, string, string, string) - // if possible. - // - if (b.method == TypeManager.string_concat_string_string || - b.method == TypeManager.string_concat_string_string_string){ - int count = b.Arguments.Count; - - if (count == 2){ - ArrayList bargs = new ArrayList (3); - bargs.AddRange (b.Arguments); - bargs.Add (new Argument (right, Argument.AType.Expression)); - return new BinaryMethod ( - TypeManager.string_type, - TypeManager.string_concat_string_string_string, bargs); - } else if (count == 3){ - ArrayList bargs = new ArrayList (4); - bargs.AddRange (b.Arguments); - bargs.Add (new Argument (right, Argument.AType.Expression)); - return new BinaryMethod ( - TypeManager.string_type, - TypeManager.string_concat_string_string_string_string, bargs); - } - } - } + // Simple constant folding + if (left is StringConstant && right is StringConstant) + return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value); - // string + string - method = TypeManager.string_concat_string_string; - } else { - // string + object - method = TypeManager.string_concat_object_object; - right = Convert.ImplicitConversion ( - ec, right, TypeManager.object_type, loc); - if (right == null){ - Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); - return null; - } - } + if (l == TypeManager.string_type || r == TypeManager.string_type) { - // - // Cascading concats will hold up to 2 arguments, any extras will be - // reallocated above. - // - ArrayList args = new ArrayList (2); - args.Add (new Argument (left, Argument.AType.Expression)); - args.Add (new Argument (right, Argument.AType.Expression)); - - return new BinaryMethod (TypeManager.string_type, method, args); - } else if (r == TypeManager.string_type){ - // object + string - - if (l == TypeManager.void_type) { + if (r == TypeManager.void_type || l == TypeManager.void_type) { Error_OperatorCannotBeApplied (); return null; } - left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc); - if (left == null){ - Error_OperatorCannotBeApplied (loc, OperName (oper), l, r); - return null; + // try to fold it in on the left + if (left is StringConcat) { + + // + // We have to test here for not-null, since we can be doubly-resolved + // take care of not appending twice + // + if (type == null){ + type = TypeManager.string_type; + ((StringConcat) left).Append (ec, right); + return left.Resolve (ec); + } else { + return left; + } } - ArrayList args = new ArrayList (2); - args.Add (new Argument (left, Argument.AType.Expression)); - args.Add (new Argument (right, Argument.AType.Expression)); - return new BinaryMethod (TypeManager.string_type, TypeManager.string_concat_object_object, args); + // Otherwise, start a new concat expression + return new StringConcat (ec, loc, left, right).Resolve (ec); } // @@ -2735,13 +2736,16 @@ namespace Mono.CSharp { oper == Operator.BitwiseOr || oper == Operator.ExclusiveOr){ if (l == r){ - if (!((l == TypeManager.int32_type) || - (l == TypeManager.uint32_type) || - (l == TypeManager.short_type) || - (l == TypeManager.ushort_type) || - (l == TypeManager.int64_type) || - (l == TypeManager.uint64_type))){ + if (((l == TypeManager.int32_type) || + (l == TypeManager.uint32_type) || + (l == TypeManager.short_type) || + (l == TypeManager.ushort_type) || + (l == TypeManager.int64_type) || + (l == TypeManager.uint64_type))){ type = l; + } else { + Error_OperatorCannotBeApplied (); + return null; } } else { Error_OperatorCannotBeApplied (); @@ -2813,32 +2817,25 @@ namespace Mono.CSharp { // but on top of that we want for == and != to use a special path // if we are comparing against null // - if (oper == Operator.Equality || oper == Operator.Inequality) { + if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) { bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue; - if (left is NullLiteral || left is IntConstant && ((IntConstant) left).Value == 0) { - right.Emit (ec); - if (my_on_true) - ig.Emit (OpCodes.Brtrue, target); - else - ig.Emit (OpCodes.Brfalse, target); + // + // put the constant on the rhs, for simplicity + // + if (left is Constant) { + Expression swap = right; + right = left; + left = swap; + } - return; - } else if (right is NullLiteral || right is IntConstant && ((IntConstant) right).Value == 0){ + if (((Constant) right).IsZeroInteger) { left.Emit (ec); if (my_on_true) ig.Emit (OpCodes.Brtrue, target); else ig.Emit (OpCodes.Brfalse, target); - return; - } else if (left is BoolConstant){ - right.Emit (ec); - if (my_on_true != ((BoolConstant) left).Value) - ig.Emit (OpCodes.Brtrue, target); - else - ig.Emit (OpCodes.Brfalse, target); - return; } else if (right is BoolConstant){ left.Emit (ec); @@ -2890,7 +2887,7 @@ namespace Mono.CSharp { right.Emit (ec); Type t = left.Type; - bool isUnsigned = is_unsigned (t); + bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type; switch (oper){ case Operator.Equality: @@ -2934,9 +2931,6 @@ namespace Mono.CSharp { break; case Operator.LessThanOrEqual: - if (t == TypeManager.double_type || t == TypeManager.float_type) - isUnsigned = true; - if (onTrue) if (isUnsigned) ig.Emit (OpCodes.Ble_Un, target); @@ -2951,8 +2945,6 @@ namespace Mono.CSharp { case Operator.GreaterThanOrEqual: - if (t == TypeManager.double_type || t == TypeManager.float_type) - isUnsigned = true; if (onTrue) if (isUnsigned) ig.Emit (OpCodes.Bge_Un, target); @@ -3005,7 +2997,7 @@ namespace Mono.CSharp { ig.MarkLabel (end); return; } - + left.Emit (ec); right.Emit (ec); @@ -3180,6 +3172,137 @@ namespace Mono.CSharp { } } + // + // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string + // b, c, d... may be strings or objects. + // + public class StringConcat : Expression { + ArrayList operands; + bool invalid = false; + + + public StringConcat (EmitContext ec, Location loc, Expression left, Expression right) + { + this.loc = loc; + type = TypeManager.string_type; + eclass = ExprClass.Value; + + operands = new ArrayList (2); + Append (ec, left); + Append (ec, right); + } + + public override Expression DoResolve (EmitContext ec) + { + if (invalid) + return null; + + return this; + } + + public void Append (EmitContext ec, Expression operand) + { + // + // 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); + return; + } + } + + // + // Conversion to object + // + if (operand.Type != TypeManager.string_type) { + Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc); + + if (no == null) { + Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type); + invalid = true; + } + operand = no; + } + + operands.Add (operand); + } + + public override void Emit (EmitContext ec) + { + MethodInfo concat_method = null; + + // + // Are we also concating objects? + // + bool is_strings_only = true; + + // + // Do conversion to arguments; check for strings only + // + for (int i = 0; i < operands.Count; i ++) { + Expression e = (Expression) operands [i]; + is_strings_only &= e.Type == TypeManager.string_type; + } + + for (int i = 0; i < operands.Count; i ++) { + Expression e = (Expression) operands [i]; + + if (! is_strings_only && e.Type == TypeManager.string_type) { + // need to make sure this is an object, because the EmitParams + // method might look at the type of this expression, see it is a + // string and emit a string [] when we want an object []; + + e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc); + } + operands [i] = new Argument (e, Argument.AType.Expression); + } + + // + // Find the right method + // + switch (operands.Count) { + case 1: + // + // This should not be possible, because simple constant folding + // is taken care of in the Binary code. + // + throw new Exception ("how did you get here?"); + + case 2: + concat_method = is_strings_only ? + TypeManager.string_concat_string_string : + TypeManager.string_concat_object_object ; + break; + case 3: + concat_method = is_strings_only ? + TypeManager.string_concat_string_string_string : + TypeManager.string_concat_object_object_object ; + break; + case 4: + // + // There is not a 4 param overlaod for object (the one that there is + // is actually a varargs methods, and is only in corlib because it was + // introduced there before.). + // + if (!is_strings_only) + goto default; + + concat_method = TypeManager.string_concat_string_string_string_string; + break; + default: + concat_method = is_strings_only ? + TypeManager.string_concat_string_dot_dot_dot : + TypeManager.string_concat_object_dot_dot_dot ; + break; + } + + Invocation.EmitArguments (ec, concat_method, operands); + ec.ig.Emit (OpCodes.Call, concat_method); + } + } + // // Object created with +/= on delegates // @@ -3252,6 +3375,7 @@ namespace Mono.CSharp { } Expression op_true, op_false, op; + LocalTemporary left_temp; public override Expression DoResolve (EmitContext ec) { @@ -3264,8 +3388,10 @@ namespace Mono.CSharp { return null; } + left_temp = new LocalTemporary (ec, type); + ArrayList arguments = new ArrayList (); - arguments.Add (new Argument (left, Argument.AType.Expression)); + arguments.Add (new Argument (left_temp, Argument.AType.Expression)); arguments.Add (new Argument (right, Argument.AType.Expression)); method = Invocation.OverloadResolve ( ec, (MethodGroupExpr) operator_group, arguments, false, loc) @@ -3277,8 +3403,8 @@ namespace Mono.CSharp { op = new StaticCallExpr (method, arguments, loc); - op_true = GetOperatorTrue (ec, left, loc); - op_false = GetOperatorFalse (ec, left, loc); + op_true = GetOperatorTrue (ec, left_temp, loc); + op_false = GetOperatorFalse (ec, left_temp, loc); if ((op_true == null) || (op_false == null)) { Error218 (); return null; @@ -3295,8 +3421,11 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Nop); - (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false); left.Emit (ec); + left_temp.Store (ec); + + (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false); + left_temp.Emit (ec); ig.Emit (OpCodes.Br, end_target); ig.MarkLabel (false_target); op.Emit (ec); @@ -3607,6 +3736,8 @@ namespace Mono.CSharp { return null; } + CheckObsoleteAttribute (e.Type); + if (local_info.LocalBuilder == null) return ec.RemapLocalLValue (local_info, right_side); @@ -3865,7 +3996,8 @@ namespace Mono.CSharp { public enum AType : byte { Expression, Ref, - Out + Out, + ArgList }; public readonly AType ArgType; @@ -3902,6 +4034,9 @@ namespace Mono.CSharp { public static string FullDesc (Argument a) { + if (a.ArgType == AType.ArgList) + return "__arglist"; + return (a.ArgType == AType.Ref ? "ref " : (a.ArgType == AType.Out ? "out " : "")) + TypeManager.CSharpName (a.Expr.Type); @@ -3911,7 +4046,7 @@ namespace Mono.CSharp { { ConstructedType ctype = Expr as ConstructedType; if (ctype != null) - Expr = ctype.GetMemberAccess (ec); + Expr = ctype.GetSimpleName (ec); // FIXME: csc doesn't report any error if you try to use `ref' or // `out' in a delegate creation expression. @@ -3940,6 +4075,24 @@ namespace Mono.CSharp { 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.Error (197, loc, + "Can not pass a type that derives from MarshalByRefObject with out or ref"); + return false; + } + } + } + } if (Expr.eclass != ExprClass.Variable){ // @@ -3985,8 +4138,9 @@ namespace Mono.CSharp { pr.AddressOf (ec, mode); } - } else + } else { ((IMemoryLocation)Expr).AddressOf (ec, mode); + } } else Expr.Emit (ec); } @@ -4070,8 +4224,7 @@ namespace Mono.CSharp { " does not resolve its type"); // - // This is a special case since csc behaves this way. I can't find - // it anywhere in the spec but oh well ... + // This is a special case since csc behaves this way. // if (argument_expr is NullLiteral && p == TypeManager.string_type && @@ -4082,6 +4235,25 @@ namespace Mono.CSharp { q == TypeManager.string_type) return 0; + // + // csc behaves this way so we emulate it. Basically, if the argument + // is null and one of the types to compare is 'object' and the other + // is a reference type, we prefer the other. + // + // I can't find this anywhere in the spec but we can interpret this + // to mean that null can be of any type you wish in such a context + // + if (p != null && q != null) { + if (argument_expr is NullLiteral && + !p.IsValueType && + q == TypeManager.object_type) + return 1; + else if (argument_expr is NullLiteral && + !q.IsValueType && + p == TypeManager.object_type) + return 0; + } + if (p == q) return 0; @@ -4238,7 +4410,6 @@ namespace Mono.CSharp { // best method, we cant tell. This happens // if we have: // - // // interface IFoo { // void DoIt (); // } @@ -4253,10 +4424,12 @@ namespace Mono.CSharp { // // However, we have to consider that // Trim (); is better than Trim (params char[] chars); + // if (cand_count == 0 && argument_count == 0) return best == null || best_params ? 1 : 0; - if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) + if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) && + (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST)) if (cand_count != argument_count) return 0; @@ -4338,6 +4511,9 @@ namespace Mono.CSharp { { string ret_type = ""; + if (mb == null) + return ""; + if (mb is MethodInfo) ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType); @@ -4410,20 +4586,22 @@ namespace Mono.CSharp { } static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me, - ArrayList arguments, ref MethodBase candidate) + ArrayList arguments, bool do_varargs, + ref MethodBase candidate) { if (!me.HasTypeArguments && !InferParamsTypeArguments (ec, arguments, ref candidate)) return false; - return IsParamsMethodApplicable (ec, arguments, candidate); + return IsParamsMethodApplicable (ec, arguments, candidate, do_varargs); } /// /// Determines if the candidate method, if a params method, is applicable /// in its expanded form to the given set of arguments /// - static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate) + static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, + MethodBase candidate, bool do_varargs) { int arg_count; @@ -4439,10 +4617,18 @@ namespace Mono.CSharp { if (pd_count == 0) return false; - if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) + int count = pd_count - 1; + if (do_varargs) { + if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST) + return false; + if (pd_count != arg_count) + return false; + } else { + if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS) return false; + } - if (pd_count - 1 > arg_count) + if (count > arg_count) return false; if (pd_count == 1 && arg_count == 0) @@ -4453,7 +4639,7 @@ namespace Mono.CSharp { // remains is when the number of parameters is // less than or equal to the argument count. // - for (int i = 0; i < pd_count - 1; ++i) { + for (int i = 0; i < count; ++i) { Argument a = (Argument) arguments [i]; @@ -4484,6 +4670,14 @@ namespace Mono.CSharp { } + if (do_varargs) { + Argument a = (Argument) arguments [count]; + if (!(a.Expr is Arglist)) + return false; + + return true; + } + Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1)); for (int i = pd_count - 1; i < arg_count; i++) { @@ -4561,8 +4755,6 @@ namespace Mono.CSharp { return true; } - - /// /// Find the Applicable Function Members (7.4.2.1) /// @@ -4593,6 +4785,8 @@ namespace Mono.CSharp { // and whether it is being considered in its // normal or expanded form // + // false is normal form, true is expanded form + // Hashtable candidate_to_form = new PtrHashtable (); @@ -4634,9 +4828,18 @@ namespace Mono.CSharp { applicable_type = candidate.DeclaringType; found_applicable = true; candidate_to_form [candidate] = false; - } else if (IsParamsMethodApplicable (ec, me, Arguments, ref methods [i])) { + } else if (IsParamsMethodApplicable ( + ec, me, Arguments,false, ref methods [i])) { // Candidate is applicable in expanded form - MethodBase candidate = methods [i]; + MethodBase candidate = methods [i]; + candidates.Add (candidate); + applicable_type = candidate.DeclaringType; + found_applicable = true; + candidate_to_form [candidate] = true; + } else if (IsParamsMethodApplicable ( + ec, me, Arguments,true, ref methods [i])) { + // Candidate is applicable in expanded form + MethodBase candidate = methods [i]; candidates.Add (candidate); applicable_type = candidate.DeclaringType; found_applicable = true; @@ -4751,9 +4954,9 @@ namespace Mono.CSharp { // applicable so we debar the params // method. // - if ((IsParamsMethodApplicable (ec, Arguments, candidate) && - IsApplicable (ec, Arguments, method))) - continue; + // if ((IsParamsMethodApplicable (ec, Arguments, candidate) && +// IsApplicable (ec, Arguments, method))) +// continue; bool cand_params = (bool) candidate_to_form [candidate]; int x = BetterFunction (ec, Arguments, @@ -4839,6 +5042,8 @@ namespace Mono.CSharp { if (chose_params_expanded) parameter_type = TypeManager.GetElementType (parameter_type); + } else if (pm == Parameter.Modifier.ARGLIST){ + continue; } else { // // Check modifiers @@ -5141,7 +5346,7 @@ namespace Mono.CSharp { is_base = true; if (expr is ConstructedType) - expr = ((ConstructedType) expr).GetMemberAccess (ec); + expr = ((ConstructedType) expr).GetSimpleName (ec); expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); if (expr == null) @@ -5182,8 +5387,20 @@ namespace Mono.CSharp { MethodInfo mi = method as MethodInfo; if (mi != null) { type = TypeManager.TypeToCoreType (mi.ReturnType); - if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) + if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) { SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name); + return null; + } + + Expression iexpr = mg.InstanceExpression; + if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) { + if (mg.IdenticalTypeName) + mg.InstanceExpression = null; + else { + MemberAccess.error176 (loc, mi.Name); + return null; + } + } } if (type.IsPointer){ @@ -5220,23 +5437,15 @@ namespace Mono.CSharp { int count = arguments.Count - idx; Argument a = (Argument) arguments [idx]; Type t = a.Expr.Type; - string array_type; - if (t.FullName != null) - array_type = t.FullName + "[]"; - else - array_type = t.Name + "[]"; - LocalBuilder array; - array = ig.DeclareLocal (TypeManager.LookupType (array_type)); IntConstant.EmitInt (ig, count); ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t)); - ig.Emit (OpCodes.Stloc, array); int top = arguments.Count; for (int j = idx; j < top; j++){ a = (Argument) arguments [j]; - ig.Emit (OpCodes.Ldloc, array); + ig.Emit (OpCodes.Dup); IntConstant.EmitInt (ig, j - idx); bool is_stobj, has_type_arg; @@ -5251,7 +5460,6 @@ namespace Mono.CSharp { else ig.Emit (op); } - ig.Emit (OpCodes.Ldloc, array); } /// @@ -5317,6 +5525,40 @@ namespace Mono.CSharp { } } + static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb, + ArrayList arguments) + { + ParameterData pd = GetParameterData (mb); + + if (arguments == null) + return new Type [0]; + + Argument a = (Argument) arguments [pd.Count - 1]; + Arglist list = (Arglist) a.Expr; + + return list.ArgumentTypes; + } + + /// + /// This checks the ConditionalAttribute on the method + /// + static bool IsMethodExcluded (MethodBase method, EmitContext ec) + { + if (method.IsConstructor) + return false; + + IMethodData md = TypeManager.GetMethod (method); + if (md != null) + return md.IsExcluded (ec); + + // For some methods (generated by delegate class) GetMethod returns null + // because they are not included in builder_to_method table + if (method.DeclaringType is TypeBuilder) + return false; + + return AttributeTester.IsConditionalMethodExcluded (method); + } + /// /// is_base tells whether we want to force the use of the `call' /// opcode instead of using callvirt. Call is required to call @@ -5362,13 +5604,24 @@ namespace Mono.CSharp { } // - // This checks the `ConditionalAttribute' on the method, and the - // ObsoleteAttribute + // This checks ObsoleteAttribute on the method and on the declaring type // - TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc); - if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0) - return; - if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0) + ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method); + 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); + } + + + oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc); + } + + if (IsMethodExcluded (method, ec)) return; if (!is_static){ @@ -5423,23 +5676,29 @@ namespace Mono.CSharp { } EmitArguments (ec, method, Arguments); + + OpCode call_op; + if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)) + call_op = OpCodes.Call; + else + call_op = OpCodes.Callvirt; + + if ((method.CallingConvention & CallingConventions.VarArgs) != 0) { + Type[] varargs_types = GetVarargsTypes (ec, method, Arguments); + ig.EmitCall (call_op, (MethodInfo) method, varargs_types); + return; + } + // // If you have: // this.DoFoo (); // and DoFoo is not virtual, you can omit the callvirt, // because you don't need the null checking behavior. // - if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){ - if (method is MethodInfo) { - ig.Emit (OpCodes.Call, (MethodInfo) method); - } else - ig.Emit (OpCodes.Call, (ConstructorInfo) method); - } else { if (method is MethodInfo) - ig.Emit (OpCodes.Callvirt, (MethodInfo) method); + ig.Emit (call_op, (MethodInfo) method); else - ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method); - } + ig.Emit (call_op, (ConstructorInfo) method); } public override void Emit (EmitContext ec) @@ -5669,6 +5928,8 @@ namespace Mono.CSharp { if (type == null) return null; + CheckObsoleteAttribute (type); + bool IsDelegate = TypeManager.IsDelegateType (type); if (IsDelegate){ @@ -5716,7 +5977,8 @@ namespace Mono.CSharp { return this; Expression ml; - ml = MemberLookupFinal (ec, null, type, ".ctor", + ml = MemberLookupFinal (ec, type, type, ".ctor", + // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'. MemberTypes.Constructor, AllBindingFlags | BindingFlags.DeclaredOnly, loc); @@ -5887,7 +6149,7 @@ namespace Mono.CSharp { /// initialization data and the other which does not need dimensions /// specified but where initialization data is mandatory. /// - public class ArrayCreation : ExpressionStatement { + public class ArrayCreation : Expression { Expression requested_base_type; ArrayList initializers; @@ -6451,7 +6713,7 @@ namespace Mono.CSharp { // // Emits the initializers for the array // - void EmitStaticInitializers (EmitContext ec, bool is_expression) + void EmitStaticInitializers (EmitContext ec) { // // First, the static data @@ -6463,8 +6725,7 @@ namespace Mono.CSharp { fb = RootContext.MakeStaticData (data); - if (is_expression) - ig.Emit (OpCodes.Dup); + ig.Emit (OpCodes.Dup); ig.Emit (OpCodes.Ldtoken, fb); ig.Emit (OpCodes.Call, TypeManager.void_initializearray_array_fieldhandle); @@ -6476,15 +6737,12 @@ namespace Mono.CSharp { // // This always expect the top value on the stack to be the array // - void EmitDynamicInitializers (EmitContext ec, bool is_expression) + void EmitDynamicInitializers (EmitContext ec) { ILGenerator ig = ec.ig; int dims = bounds.Count; int [] current_pos = new int [dims]; int top = array_data.Count; - LocalBuilder temp = ig.DeclareLocal (type); - - ig.Emit (OpCodes.Stloc, temp); MethodInfo set = null; @@ -6526,7 +6784,7 @@ namespace Mono.CSharp { num_automatic_initializers <= max_automatic_initializers) { Type etype = e.Type; - ig.Emit (OpCodes.Ldloc, temp); + ig.Emit (OpCodes.Dup); for (int idx = 0; idx < dims; idx++) IntConstant.EmitInt (ig, current_pos [idx]); @@ -6572,9 +6830,6 @@ namespace Mono.CSharp { current_pos [j] = 0; } } - - if (is_expression) - ig.Emit (OpCodes.Ldloc, temp); } void EmitArrayArguments (EmitContext ec) @@ -6592,7 +6847,7 @@ namespace Mono.CSharp { } } - void DoEmit (EmitContext ec, bool is_statement) + public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; @@ -6616,23 +6871,13 @@ namespace Mono.CSharp { // initialized. num_automatic_initializers will always be zero. See // CheckIndices. if (num_automatic_initializers > max_automatic_initializers) - EmitStaticInitializers (ec, dynamic_initializers || !is_statement); + EmitStaticInitializers (ec); if (dynamic_initializers) - EmitDynamicInitializers (ec, !is_statement); + EmitDynamicInitializers (ec); } } - public override void Emit (EmitContext ec) - { - DoEmit (ec, false); - } - - public override void EmitStatement (EmitContext ec) - { - DoEmit (ec, true); - } - public object EncodeAsAttribute () { if (!is_one_dimensional){ @@ -6763,8 +7008,8 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { ILGenerator ig = ec.ig; - - ig.Emit (OpCodes.Ldarg_0); + + ec.EmitThis (); if (ec.TypeContainer is Struct) ig.Emit (OpCodes.Ldobj, type); } @@ -6774,7 +7019,7 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; if (ec.TypeContainer is Struct){ - ig.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); source.Emit (ec); ig.Emit (OpCodes.Stobj, type); } else { @@ -6785,7 +7030,7 @@ namespace Mono.CSharp { public void AddressOf (EmitContext ec, AddressOp mode) { - ec.ig.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); // FIMXE // FIGURE OUT WHY LDARG_S does not work @@ -6798,6 +7043,85 @@ namespace Mono.CSharp { } } + /// + /// Represents the `__arglist' construct + /// + public class ArglistAccess : Expression + { + public ArglistAccess (Location loc) + { + this.loc = loc; + } + + public bool ResolveBase (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.HasVarargs) { + Error (190, "The __arglist construct is valid only within " + + "a variable argument method."); + return null; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + ec.ig.Emit (OpCodes.Arglist); + } + } + + /// + /// Represents the `__arglist (....)' construct + /// + public class Arglist : Expression + { + public readonly Argument[] Arguments; + + public Arglist (Argument[] args, Location l) + { + Arguments = args; + loc = l; + } + + public Type[] ArgumentTypes { + get { + Type[] retval = new Type [Arguments.Length]; + for (int i = 0; i < Arguments.Length; i++) + retval [i] = Arguments [i].Type; + return retval; + } + } + + public override Expression DoResolve (EmitContext ec) + { + eclass = ExprClass.Variable; + type = TypeManager.runtime_argument_handle_type; + + foreach (Argument arg in Arguments) { + if (!arg.Resolve (ec, loc)) + return null; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + foreach (Argument arg in Arguments) + arg.Emit (ec); + } + } + // // This produces the value that renders an instance, used by the iterators code // @@ -6847,6 +7171,8 @@ namespace Mono.CSharp { return null; } + CheckObsoleteAttribute (typearg); + type = TypeManager.type_type; eclass = ExprClass.Type; return this; @@ -6913,6 +7239,11 @@ namespace Mono.CSharp { } type_queried = QueriedType.Type; + if (type_queried == null) + return null; + + CheckObsoleteAttribute (type_queried); + if (!TypeManager.IsUnmanagedType (type_queried)){ Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")"); return null; @@ -6962,7 +7293,7 @@ namespace Mono.CSharp { } } - static void error176 (Location loc, string name) + public static void error176 (Location loc, string name) { Report.Error (176, loc, "Static member `" + name + "' cannot be accessed " + @@ -6970,21 +7301,13 @@ namespace Mono.CSharp { "type name instead"); } - static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc) + public static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc) { - if (left_original == null) - return false; - - if (!(left_original is SimpleName)) + SimpleName sn = left_original as SimpleName; + if (sn == null || left == null || left.Type.Name != sn.Name) return false; - SimpleName sn = (SimpleName) left_original; - - TypeExpr t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc); - if (t != null) - return true; - - return false; + return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null; } public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup, @@ -7009,17 +7332,17 @@ namespace Mono.CSharp { if (member_lookup is FieldExpr){ FieldExpr fe = (FieldExpr) member_lookup; - FieldInfo fi = fe.FieldInfo; + FieldInfo fi = fe.FieldInfo.Mono_GetGenericFieldDefinition (); Type decl_type = fi.DeclaringType; if (fi is FieldBuilder) { Const c = TypeManager.LookupConstant ((FieldBuilder) fi); if (c != null) { - object o = c.LookupConstantValue (); - if (o == null) + object o; + if (!c.LookupConstantValue (out o)) return null; - + object real_value = ((Constant) c.Expr).GetValue (); return Constantify (real_value, fi.FieldType); @@ -7038,7 +7361,7 @@ namespace Mono.CSharp { if (decl_type.IsSubclassOf (TypeManager.enum_type)) { if (left_is_explicit && !left_is_type && - !IdenticalNameAndTypeName (ec, left_original, loc)) { + !IdenticalNameAndTypeName (ec, left_original, member_lookup, loc)) { error176 (loc, fe.FieldInfo.Name); return null; } @@ -7092,6 +7415,7 @@ namespace Mono.CSharp { // accessors and private field etc so there's no need // to transform ourselves. // + ee.InstanceExpression = left; return ee; } @@ -7105,21 +7429,23 @@ namespace Mono.CSharp { if (!left_is_explicit) left = null; + ee.InstanceExpression = left; + return ResolveMemberAccess (ec, ml, left, loc, left_original); } } if (member_lookup is IMemberExpr) { IMemberExpr me = (IMemberExpr) member_lookup; + MethodGroupExpr mg = me as MethodGroupExpr; if (left_is_type){ - MethodGroupExpr mg = me as MethodGroupExpr; if ((mg != null) && left_is_explicit && left.Type.IsInterface) mg.IsExplicitImpl = left_is_explicit; if (!me.IsStatic){ if ((ec.IsFieldInitializer || ec.IsStatic) && - IdenticalNameAndTypeName (ec, left_original, loc)) + IdenticalNameAndTypeName (ec, left_original, member_lookup, loc)) return member_lookup; SimpleName.Error_ObjectRefRequired (ec, loc, me.Name); @@ -7128,7 +7454,7 @@ namespace Mono.CSharp { } else { if (!me.IsInstance){ - if (IdenticalNameAndTypeName (ec, left_original, loc)) + if (IdenticalNameAndTypeName (ec, left_original, left, loc)) return member_lookup; if (left_is_explicit) { @@ -7158,6 +7484,9 @@ namespace Mono.CSharp { } } + if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, left, loc)) + mg.IdenticalTypeName = true; + me.InstanceExpression = left; } @@ -7166,7 +7495,7 @@ namespace Mono.CSharp { Console.WriteLine ("Left is: " + left); Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet"); - Environment.Exit (0); + Environment.Exit (1); return null; } @@ -7184,7 +7513,7 @@ namespace Mono.CSharp { // Expression original = expr; - expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis); + expr = expr.Resolve (ec, flags | ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis); if (expr == null) return null; @@ -7210,8 +7539,7 @@ namespace Mono.CSharp { expr_type = ((TypeExpr) expr).ResolveType (ec); if (!ec.DeclSpace.CheckAccessLevel (expr_type)){ - Error (122, "`" + expr_type + "' " + - "is inaccessible because of its protection level"); + Report.Error_T (122, loc, expr_type); return null; } @@ -7222,9 +7550,23 @@ namespace Mono.CSharp { object value = en.LookupEnumValue (ec, Identifier, loc); if (value != null){ + ObsoleteAttribute oa = en.GetObsoleteAttribute (ec, Identifier); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location); + } + Constant c = Constantify (value, en.UnderlyingType); return new EnumConstant (c, expr_type); } + } else { + CheckObsoleteAttribute (expr_type); + + FieldInfo fi = expr_type.GetField (Identifier); + if (fi != null) { + ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location); + } } } } else @@ -7289,54 +7631,7 @@ namespace Mono.CSharp { if (mg == null) throw new InternalErrorException (); - if (args.Resolve (ec) == false) - return null; - - Type[] atypes = args.Arguments; - - int first_count = 0; - MethodInfo first = null; - - ArrayList list = new ArrayList (); - foreach (MethodBase mb in mg.Methods) { - MethodInfo mi = mb as MethodInfo; - if ((mi == null) || !mi.HasGenericParameters) - continue; - - Type[] gen_params = mi.GetGenericArguments (); - - if (first == null) { - first = mi; - first_count = gen_params.Length; - } - - if (gen_params.Length != atypes.Length) - continue; - - list.Add (mi.BindGenericParameters (atypes)); - } - - if (list.Count > 0) { - MethodGroupExpr new_mg = new MethodGroupExpr ( - list, mg.Location); - new_mg.InstanceExpression = mg.InstanceExpression; - new_mg.HasTypeArguments = true; - return new_mg; - } - - string name = expr_type + "." + Identifier; - - if (first != null) - Report.Error ( - 305, loc, "Using the generic method `{0}' " + - "requires {1} type arguments", name, - first_count); - else - Report.Error ( - 308, loc, "The non-generic method `{0}' " + - "cannot be used with type arguments", name); - - return null; + return mg.ResolveGeneric (ec, args); } // The following DoResolve/DoResolveLValue will do the definite assignment @@ -7761,7 +8056,9 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldelem_R8); else if (type == TypeManager.intptr_type) ig.Emit (OpCodes.Ldelem_I); - else if (type.IsValueType){ + else if (TypeManager.IsEnumType (type)){ + EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type)); + } else if (type.IsValueType){ ig.Emit (OpCodes.Ldelema, type); ig.Emit (OpCodes.Ldobj, type); } else if (type.IsGenericParameter) @@ -8053,7 +8350,7 @@ namespace Mono.CSharp { MemberInfo [] mi = TypeManager.MemberLookup ( caller_type, caller_type, lookup_type, MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance | - BindingFlags.DeclaredOnly, p_name); + BindingFlags.DeclaredOnly, p_name, null); if (mi == null || mi.Length == 0) return null; @@ -8352,6 +8649,11 @@ namespace Mono.CSharp { Error (1511, "Keyword base is not allowed in static method"); return null; } + + if (ec.IsFieldInitializer){ + Error (1512, "Keyword base is not available in the current context"); + return null; + } member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member, AllMemberTypes, AllBindingFlags, @@ -8518,6 +8820,12 @@ namespace Mono.CSharp { if (ltype == null) return null; + if ((ltype == TypeManager.void_type) && (dim != "*")) { + Report.Error (1547, Location, + "Keyword 'void' cannot be used in this context"); + return null; + } + int pos = 0; while ((pos < dim.Length) && (dim [pos] == '[')) { pos++;