X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fexpression.cs;h=9005f6641e63b54bd625e0bb7dea0b21d758e0bc;hb=7713641ae9075059e06b2c3c78944c83a46ba393;hp=8ca5111f8ed0c82cb48f16f3445066ad0f08b9d8;hpb=b2e0cde0532cb523fca8f9dfb23f1b939c4c8a69;p=mono.git diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 8ca5111f8ed..9005f6641e6 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -3,6 +3,7 @@ // // Author: // Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) // // (C) 2001, 2002, 2003 Ximian, Inc. // (C) 2003, 2004 Novell, Inc. @@ -358,7 +359,7 @@ namespace Mono.CSharp { op_name = oper_names [(int) Oper]; - mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); + mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); if (mg != null) { Expression e = StaticCallExpr.MakeSimpleCall ( @@ -612,7 +613,7 @@ namespace Mono.CSharp { throw new Exception ("This should be caught by Resolve"); case Operator.UnaryNegation: - if (ec.CheckState) { + if (ec.CheckState && type != TypeManager.float_type && type != TypeManager.double_type) { ig.Emit (OpCodes.Ldc_I4_0); if (type == TypeManager.int64_type) ig.Emit (OpCodes.Conv_U8); @@ -849,7 +850,7 @@ namespace Mono.CSharp { else op_name = "op_Decrement"; - mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); + mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc); if (mg != null) { method = StaticCallExpr.MakeSimpleCall ( @@ -879,7 +880,7 @@ namespace Mono.CSharp { if (expr == null) return null; } else { - expr.Error_UnexpectedKind (ec, "variable, indexer or property access", loc); + expr.Error_UnexpectedKind (ec.DeclContainer, "variable, indexer or property access", loc); return null; } @@ -1251,7 +1252,12 @@ namespace Mono.CSharp { Error_CannotConvertType (etype, probe_type, loc); return null; - } + } + + public override bool GetAttributableValue (out object value) + { + return expr.GetAttributableValue (out value); + } } /// @@ -1326,9 +1332,14 @@ namespace Mono.CSharp { Constant c = expr as Constant; if (c != null) { - c = c.TryReduce (ec, type, loc); - if (c != null) - return c; + try { + c = c.TryReduce (ec, type, loc); + if (c != null) + return c; + } + catch (OverflowException) { + return null; + } } if (type.IsPointer && !ec.InUnsafe) { @@ -1831,10 +1842,10 @@ namespace Mono.CSharp { string op = oper_names [(int) oper]; MethodGroupExpr union; - left_operators = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc); + left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc); if (r != l){ right_operators = MemberLookup ( - ec, r, op, MemberTypes.Method, AllBindingFlags, loc); + ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc); union = Invocation.MakeUnionSet (left_operators, right_operators, loc); } else union = (MethodGroupExpr) left_operators; @@ -2309,6 +2320,9 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { + if (left == null) + return null; + if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) { left = ((ParenthesizedExpression) left).Expr; left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type); @@ -2373,6 +2387,11 @@ namespace Mono.CSharp { if (rc is EnumConstant && lc != null && lc.IsZeroInteger) return rc; + } else if (oper == Operator.LogicalAnd) { + if (rc != null && rc.IsDefaultValue && rc.Type == TypeManager.bool_type) + return rc; + if (lc != null && lc.IsDefaultValue && lc.Type == TypeManager.bool_type) + return lc; } if (rc != null && lc != null){ @@ -3401,7 +3420,7 @@ namespace Mono.CSharp { local_info = Block.GetLocalInfo (Name); // is out param - if (lvalue_right_side == EmptyExpression.Null) + if (lvalue_right_side == EmptyExpression.OutAccess) local_info.Used = true; is_readonly = local_info.ReadOnly; @@ -3412,9 +3431,12 @@ namespace Mono.CSharp { VariableInfo variable_info = local_info.VariableInfo; if (lvalue_right_side != null){ if (is_readonly){ - if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.Null) + 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 ()); @@ -3584,12 +3606,11 @@ namespace Mono.CSharp { /// representation. /// public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable { - Parameters pars; - String name; + Parameter par; + string name; int idx; Block block; VariableInfo vi; - public Parameter.Modifier mod; public bool is_ref, is_out, prepared; public bool IsOut { @@ -3606,20 +3627,16 @@ namespace Mono.CSharp { LocalTemporary temp; - public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc) + public ParameterReference (Parameter par, Block block, int idx, Location loc) { - this.pars = pars; + this.par = par; + this.name = par.Name; this.block = block; this.idx = idx; - this.name = name; this.loc = loc; eclass = ExprClass.Variable; } - public ParameterReference (InternalParameters pars, Block block, int idx, Location loc) - : this (pars.Parameters, block, idx, pars.ParameterName (idx), loc) - { } - public VariableInfo VariableInfo { get { return vi; } } @@ -3627,7 +3644,7 @@ namespace Mono.CSharp { public bool VerifyFixed () { // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param). - return mod == Parameter.Modifier.NONE; + return par.ModFlags == Parameter.Modifier.NONE; } public bool IsAssigned (EmitContext ec, Location loc) @@ -3636,7 +3653,7 @@ namespace Mono.CSharp { return true; Report.Error (269, loc, - "Use of unassigned out parameter `{0}'", name); + "Use of unassigned out parameter `{0}'", par.Name); return false; } @@ -3664,18 +3681,23 @@ namespace Mono.CSharp { protected void DoResolveBase (EmitContext ec) { - type = pars.GetParameterInfo (ec, idx, out mod); + if (!par.Resolve (ec)) { + //TODO: + } + + type = par.ParameterType; + Parameter.Modifier mod = par.ModFlags; is_ref = (mod & Parameter.Modifier.ISBYREF) != 0; - is_out = (mod & Parameter.Modifier.OUT) != 0; + is_out = (mod & Parameter.Modifier.OUT) == Parameter.Modifier.OUT; eclass = ExprClass.Variable; if (is_out) vi = block.ParameterMap [idx]; if (ec.CurrentAnonymousMethod != null){ - if (is_ref){ + if (is_ref && !block.Toplevel.IsLocalParameter (name)){ Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block", - name); + par.Name); return; } @@ -3780,11 +3802,8 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; int arg_idx = idx; - if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){ - if (leave_copy) - throw new InternalErrorException (); - - ec.EmitParameter (name); + if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){ + ec.EmitParameter (name, leave_copy, prepared, ref temp); return; } @@ -3816,15 +3835,16 @@ namespace Mono.CSharp { public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { + prepared = prepare_for_load; if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){ - ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load); + ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp); return; } ILGenerator ig = ec.ig; int arg_idx = idx; - prepared = prepare_for_load; + if (!ec.MethodIsStatic) arg_idx++; @@ -3880,6 +3900,10 @@ namespace Mono.CSharp { } } + public override string ToString () + { + return "ParameterReference[" + name + "]"; + } } /// @@ -3922,10 +3946,10 @@ namespace Mono.CSharp { get { switch (ArgType) { case AType.Out: - return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF; + return Parameter.Modifier.OUT; case AType.Ref: - return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF; + return Parameter.Modifier.REF; default: return Parameter.Modifier.NONE; @@ -3973,15 +3997,17 @@ namespace Mono.CSharp { return false; } + int errors = Report.Errors; Expr = Expr.DoResolveLValue (ec, Expr); - if (Expr == null) + 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.Null); + Expr = Expr.DoResolveLValue (ec, EmptyExpression.OutAccess); ec.InRefOutArgumentResolving = false; - if (Expr == null) + if (Expr == null && errors == Report.Errors) Error_LValueRequired (loc); } else @@ -4014,20 +4040,6 @@ namespace Mono.CSharp { } } } - - if (Expr.eclass != ExprClass.Variable){ - // - // We just probe to match the CSC output - // - if (Expr.eclass == ExprClass.PropertyAccess || - Expr.eclass == ExprClass.IndexerAccess){ - Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter", - Expr.GetSignatureForError ()); - } else { - Error_LValueRequired (loc); - } - return false; - } return true; } @@ -4268,7 +4280,7 @@ namespace Mono.CSharp { return !candidate_params && best_params; } - static bool IsOverride (MethodBase cand_method, MethodBase base_method) + internal static bool IsOverride (MethodBase cand_method, MethodBase base_method) { if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType)) return false; @@ -4354,26 +4366,18 @@ namespace Mono.CSharp { return union; } - public static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me, + public static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, int arg_count, - ref MethodBase candidate) + MethodBase candidate) { return IsParamsMethodApplicable ( - ec, me, arguments, arg_count, false, ref candidate) || + ec, arguments, arg_count, candidate, false) || IsParamsMethodApplicable ( - ec, me, arguments, arg_count, true, ref candidate); + ec, arguments, arg_count, candidate, true); } - static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me, - ArrayList arguments, int arg_count, - bool do_varargs, ref MethodBase candidate) - { - return IsParamsMethodApplicable ( - ec, arguments, arg_count, candidate, do_varargs); - } - /// /// Determines if the candidate method, if a params method, is applicable /// in its expanded form to the given set of arguments @@ -4395,7 +4399,7 @@ namespace Mono.CSharp { if (pd_count != arg_count) return false; } else { - if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS) + if (!pd.HasParams) return false; } @@ -4415,9 +4419,9 @@ namespace Mono.CSharp { Argument a = (Argument) arguments [i]; Parameter.Modifier a_mod = a.Modifier & - (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF))); + (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK))); Parameter.Modifier p_mod = pd.ParameterModifier (i) & - (unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF))); + (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK))); if (a_mod == p_mod) { @@ -4425,8 +4429,8 @@ namespace Mono.CSharp { if (!Convert.ImplicitConversionExists (ec, a.Expr, pd.ParameterType (i))) - return false; - + return false; + if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { Type pt = pd.ParameterType (i); @@ -4461,19 +4465,12 @@ namespace Mono.CSharp { return true; } - public static bool IsApplicable (EmitContext ec, MethodGroupExpr me, - ArrayList arguments, int arg_count, - ref MethodBase candidate) - { - return IsApplicable (ec, arguments, arg_count, candidate); - } - /// /// Determines if the candidate method is applicable (section 14.4.2.1) /// to the given set of arguments /// - static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count, - MethodBase candidate) + public static bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count, + MethodBase candidate) { ParameterData pd = TypeManager.GetParameterData (candidate); @@ -4486,28 +4483,22 @@ namespace Mono.CSharp { Argument a = (Argument) arguments [i]; Parameter.Modifier a_mod = a.Modifier & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); + ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + Parameter.Modifier p_mod = pd.ParameterModifier (i) & - unchecked (~(Parameter.Modifier.OUT | Parameter.Modifier.REF)); + ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS); - if (a_mod == p_mod || - (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) { - if (a_mod == Parameter.Modifier.NONE) { - if (!Convert.ImplicitConversionExists (ec, - a.Expr, - pd.ParameterType (i))) - return false; - } - - if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { - Type pt = pd.ParameterType (i); + if (a_mod == p_mod) { + Type pt = pd.ParameterType (i); - if (!pt.IsByRef) - pt = TypeManager.GetReferenceType (pt); - - if (pt != a.Type) + if (a_mod == Parameter.Modifier.NONE) { + if (!Convert.ImplicitConversionExists (ec, a.Expr, pt)) return false; + continue; } + + if (pt != a.Type) + return false; } else return false; } @@ -4515,7 +4506,7 @@ namespace Mono.CSharp { return true; } - static private bool IsAncestralType (Type first_type, Type second_type) + static internal bool IsAncestralType (Type first_type, Type second_type) { return first_type != second_type && (second_type.IsSubclassOf (first_type) || @@ -4569,45 +4560,57 @@ namespace Mono.CSharp { MethodBase[] methods = me.Methods; + int nmethods = methods.Length; + + if (!me.IsBase) { + // + // Methods marked 'override' don't take part in 'applicable_type' + // computation, nor in the actual overload resolution. + // However, they still need to be emitted instead of a base virtual method. + // So, we salt them away into the 'candidate_overrides' array. + // + // In case of reflected methods, we replace each overriding method with + // its corresponding base virtual method. This is to improve compatibility + // with non-C# libraries which change the visibility of overrides (#75636) + // + int j = 0; + for (int i = 0; i < methods.Length; ++i) { + MethodBase m = methods [i]; + if (TypeManager.IsOverride (m)) { + if (candidate_overrides == null) + candidate_overrides = new ArrayList (); + candidate_overrides.Add (m); + m = TypeManager.TryGetBaseDefinition (m); + } + if (m != null) + methods [j++] = m; + } + nmethods = j; + } + + int applicable_errors = Report.Errors; + // // First we construct the set of applicable methods // bool is_sorted = true; - for (int i = 0; i < methods.Length; i++){ + for (int i = 0; i < nmethods; i++){ Type decl_type = methods [i].DeclaringType; // // If we have already found an applicable method // we eliminate all base types (Section 14.5.5.1) // - if ((applicable_type != null) && - IsAncestralType (decl_type, applicable_type)) + if (applicable_type != null && IsAncestralType (decl_type, applicable_type)) continue; - // - // Methods marked 'override' don't take part in 'applicable_type' - // computation, nor in the actual overload resolution. - // However, they still need to be emitted instead of a base virtual method. - // We avoid doing the 'applicable' test here, since it'll anyway be applied - // to the base virtual function, and IsOverride is much faster than IsApplicable. - // - if (!me.IsBase && TypeManager.IsOverride (methods [i])) { - if (candidate_overrides == null) - candidate_overrides = new ArrayList (); - candidate_overrides.Add (methods [i]); - continue; - } - // // Check if candidate is applicable (section 14.4.2.1) // Is candidate applicable in normal form? // - bool is_applicable = IsApplicable ( - ec, me, Arguments, arg_count, ref methods [i]); + bool is_applicable = IsApplicable (ec, Arguments, arg_count, methods [i]); - if (!is_applicable && - (IsParamsMethodApplicable ( - ec, me, Arguments, arg_count, ref methods [i]))) { + if (!is_applicable && IsParamsMethodApplicable (ec, Arguments, arg_count, methods [i])) { MethodBase candidate = methods [i]; if (candidate_to_form == null) candidate_to_form = new PtrHashtable (); @@ -4630,6 +4633,9 @@ namespace Mono.CSharp { } } + if (applicable_errors != Report.Errors) + return null; + int candidate_top = candidates.Count; if (applicable_type == null) { @@ -4638,7 +4644,7 @@ namespace Mono.CSharp { // return by providing info about the closest match // int errors = Report.Errors; - for (int i = 0; i < methods.Length; ++i) { + for (int i = 0; i < nmethods; ++i) { MethodBase c = (MethodBase) methods [i]; ParameterData pd = TypeManager.GetParameterData (c); @@ -4802,7 +4808,7 @@ namespace Mono.CSharp { public static void Error_WrongNumArguments (Location loc, String name, int arg_count) { Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", - name, arg_count); + name, arg_count.ToString ()); } static void Error_InvokeOnDelegate (Location loc) @@ -4821,21 +4827,20 @@ namespace Mono.CSharp { Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", TypeManager.CSharpName (delegate_type)); - string par_desc = expected_par.ParameterDesc (idx); + Parameter.Modifier mod = expected_par.ParameterModifier (idx); - if (a.Modifier != expected_par.ParameterModifier (idx)) { - if ((expected_par.ParameterModifier (idx) & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0) + string index = (idx + 1).ToString (); + if (mod != Parameter.Modifier.ARGLIST && mod != a.Modifier) { + if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0) Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword", - idx + 1, Parameter.GetModifierSignature (a.Modifier)); + index, Parameter.GetModifierSignature (a.Modifier)); else Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword", - idx + 1, Parameter.GetModifierSignature (expected_par.ParameterModifier (idx))); - return; + index, Parameter.GetModifierSignature (mod)); + } else { + Report.Error (1503, loc, "Argument {0}: Cannot convert from `{1}' to `{2}'", + index, Argument.FullDesc (a), expected_par.ParameterDesc (idx)); } - - Report.Error (1503, loc, - String.Format ("Argument {0}: Cannot convert from `{1}' to `{2}'", - idx + 1, Argument.FullDesc (a), par_desc)); } public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments, @@ -4856,15 +4861,18 @@ namespace Mono.CSharp { if (pm == Parameter.Modifier.PARAMS){ if ((pm & ~Parameter.Modifier.PARAMS) != a.Modifier) { if (!may_fail) - Error_InvalidArguments ( - loc, j, method, delegate_type, - a, pd); + Error_InvalidArguments (loc, j, method, delegate_type, a, pd); return false; } if (chose_params_expanded) parameter_type = TypeManager.GetElementType (parameter_type); - } else if (pm == Parameter.Modifier.ARGLIST){ + } 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 { // @@ -4872,9 +4880,7 @@ namespace Mono.CSharp { // if (pd.ParameterModifier (j) != a.Modifier){ if (!may_fail) - Error_InvalidArguments ( - loc, j, method, delegate_type, - a, pd); + Error_InvalidArguments (loc, j, method, delegate_type, a, pd); return false; } } @@ -4925,8 +4931,13 @@ namespace Mono.CSharp { return true; } + private bool resolved = false; public override Expression DoResolve (EmitContext ec) { + if (resolved) + return this.method == null ? null : this; + + resolved = true; // // First, resolve the expression that is used to // trigger the invocation @@ -4962,7 +4973,7 @@ namespace Mono.CSharp { } MethodGroupExpr mg = (MethodGroupExpr) expr; - method = OverloadResolve (ec, mg, Arguments, false, loc); + MethodBase method = OverloadResolve (ec, mg, Arguments, false, loc); if (method == null) return null; @@ -5019,6 +5030,7 @@ namespace Mono.CSharp { mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); eclass = ExprClass.Value; + this.method = method; return this; } @@ -5163,14 +5175,14 @@ namespace Mono.CSharp { /// /// This checks the ConditionalAttribute on the method /// - static bool IsMethodExcluded (MethodBase method, EmitContext ec) + static bool IsMethodExcluded (MethodBase method) { if (method.IsConstructor) return false; IMethodData md = TypeManager.GetMethod (method); if (md != null) - return md.IsExcluded (ec); + return md.IsExcluded (); // For some methods (generated by delegate class) GetMethod returns null // because they are not included in builder_to_method table @@ -5239,7 +5251,7 @@ namespace Mono.CSharp { method = TypeManager.void_array_copyto_array_int; } - if (ec.TestObsoleteMethodUsage) { + if (!ec.IsInObsoleteScope) { // // This checks ObsoleteAttribute on the method and on the declaring type // @@ -5254,7 +5266,7 @@ namespace Mono.CSharp { } } - if (IsMethodExcluded (method, ec)) + if (IsMethodExcluded (method)) return; if (!is_static){ @@ -5586,6 +5598,29 @@ namespace Mono.CSharp { return null; } + // + // Checks whether the type is an interface that has the + // [ComImport, CoClass] attributes and must be treated + // specially + // + public Expression CheckComImport (EmitContext ec) + { + if (!type.IsInterface) + return null; + + // + // Turn the call into: + // (the-interface-stated) (new class-referenced-in-coclassattribute ()) + // + Type real_class = AttributeTester.GetCoClassAttribute (type); + if (real_class == null) + return null; + + New proxy = new New (new TypeExpression (real_class, loc), Arguments, loc); + Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc); + return cast.Resolve (ec); + } + public override Expression DoResolve (EmitContext ec) { // @@ -5629,6 +5664,10 @@ namespace Mono.CSharp { } if (type.IsInterface || type.IsAbstract){ + RequestedType = CheckComImport (ec); + if (RequestedType != null) + return RequestedType; + Report.SymbolRelatedToPreviousError (type); Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type)); return null; @@ -5654,7 +5693,7 @@ namespace Mono.CSharp { MethodGroupExpr mg = ml as MethodGroupExpr; if (mg == null) { - ml.Error_UnexpectedKind (ec, "method group", loc); + ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc); return null; } @@ -5668,7 +5707,7 @@ namespace Mono.CSharp { method = Invocation.OverloadResolve (ec, mg, Arguments, false, loc); if (method == null) { if (almostMatchedMembers.Count != 0) - MemberLookupFailed (ec, type, type, ".ctor", null, true, loc); + MemberLookupFailed (ec.ContainerType, type, type, ".ctor", null, true, loc); return null; } @@ -5874,16 +5913,21 @@ namespace Mono.CSharp { { if (specified_dims) { Argument a = (Argument) arguments [idx]; - + if (!a.Resolve (ec, loc)) return false; - - if (!(a.Expr is Constant)) { - Error (150, "A constant value is expected"); + + Constant c = a.Expr as Constant; + if (c != null) { + c = c.ToType (TypeManager.int32_type, a.Expr.Location); + } + + if (c == null) { + Report.Error (150, a.Expr.Location, "A constant value is expected"); return false; } - - int value = (int) ((Constant) a.Expr).GetValue (); + + int value = (int) c.GetValue (); if (value != probe.Count) { Error_IncorrectArrayInitializer (); @@ -5980,10 +6024,7 @@ namespace Mono.CSharp { public bool ValidateInitializers (EmitContext ec, Type array_type) { if (initializers == null) { - if (expect_initializers) - return false; - else - return true; + return !expect_initializers; } if (underlying_type == null) @@ -5996,17 +6037,12 @@ namespace Mono.CSharp { array_data = new ArrayList (); bounds = new Hashtable (); - bool ret; - if (arguments != null) { - ret = CheckIndices (ec, initializers, 0, true); - return ret; + return CheckIndices (ec, initializers, 0, true); } else { arguments = new ArrayList (); - ret = CheckIndices (ec, initializers, 0, false); - - if (!ret) + if (!CheckIndices (ec, initializers, 0, false)) return false; UpdateIndices (ec); @@ -6016,7 +6052,7 @@ namespace Mono.CSharp { return false; } - return ret; + return true; } } @@ -6047,12 +6083,7 @@ namespace Mono.CSharp { if (array_type_expr == null) return false; - type = array_type_expr.ResolveType (ec); - - if (!type.IsArray) { - Error (622, "Can only use array initializer expressions to assign to array types. Try using a new expression instead."); - return false; - } + type = array_type_expr.ResolveType (ec); underlying_type = TypeManager.GetElementType (type); dimensions = type.GetArrayRank (); @@ -6107,11 +6138,11 @@ namespace Mono.CSharp { if (is_builtin_type) { Expression ml; - ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor, + ml = MemberLookup (ec.ContainerType, type, ".ctor", MemberTypes.Constructor, AllBindingFlags, loc); if (!(ml is MethodGroupExpr)) { - ml.Error_UnexpectedKind (ec, "method group", loc); + ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc); return null; } @@ -6479,32 +6510,33 @@ namespace Mono.CSharp { } } - public object EncodeAsAttribute () + public override bool GetAttributableValue (out object value) { if (!is_one_dimensional){ - Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); - return null; +// Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); + return base.GetAttributableValue (out value); } - if (array_data == null){ - Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); - return null; + if (array_data == null) { + Constant c = (Constant)((Argument)arguments [0]).Expr; + if (c.IsDefaultValue) { + value = new object [0]; + return true; + } +// Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); + return base.GetAttributableValue (out value); } object [] ret = new object [array_data.Count]; - int i = 0; - foreach (Expression e in array_data){ - object v; - - if (e is NullLiteral) - v = null; - else { - if (!Attribute.GetAttributeArgumentExpression (e, Location, array_element_type, out v)) - return null; + for (int i = 0; i < ret.Length; ++i) + { + if (!((Expression)array_data [i]).GetAttributableValue (out ret [i])) { + value = null; + return false; } - ret [i++] = v; } - return ret; + value = ret; + return true; } } @@ -6602,11 +6634,20 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; if (ec.TypeContainer is Struct){ - ec.EmitThis (); + ec.EmitThis (false); source.Emit (ec); - if (leave_copy) + + LocalTemporary t = null; + if (leave_copy) { + t = new LocalTemporary (ec, type); ec.ig.Emit (OpCodes.Dup); + t.Store (ec); + } + ig.Emit (OpCodes.Stobj, type); + + if (leave_copy) + t.Emit (ec); } else { throw new Exception ("how did you get here"); } @@ -6616,7 +6657,7 @@ namespace Mono.CSharp { { ILGenerator ig = ec.ig; - ec.EmitThis (); + ec.EmitThis (false); if (ec.TypeContainer is Struct) ig.Emit (OpCodes.Ldobj, type); } @@ -6637,7 +6678,7 @@ namespace Mono.CSharp { public void AddressOf (EmitContext ec, AddressOp mode) { - ec.EmitThis (); + ec.EmitThis (true); // FIMXE // FIGURE OUT WHY LDARG_S does not work @@ -6756,7 +6797,7 @@ namespace Mono.CSharp { /// Implements the typeof operator /// public class TypeOf : Expression { - public Expression QueriedType; + readonly Expression QueriedType; protected Type typearg; public TypeOf (Expression queried_type, Location l) @@ -6796,8 +6837,10 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); } - public Type TypeArg { - get { return typearg; } + public override bool GetAttributableValue (out object value) + { + value = typearg; + return true; } } @@ -6886,13 +6929,13 @@ namespace Mono.CSharp { loc = l; } - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { if (alias == "global") return new MemberAccess (RootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent); int errors = Report.Errors; - FullNamedExpression fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias); + FullNamedExpression fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias); if (fne == null) { if (errors == Report.Errors) Report.Error (432, loc, "Alias `{0}' not found", alias); @@ -6913,7 +6956,7 @@ namespace Mono.CSharp { fne = RootNamespace.Global; } else { int errors = Report.Errors; - fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias); + fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias); if (fne == null) { if (errors == Report.Errors) Report.Error (432, loc, "Alias `{0}' not found", alias); @@ -6998,7 +7041,7 @@ namespace Mono.CSharp { if (new_expr is Namespace) { Namespace ns = (Namespace) new_expr; - FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc); + FullNamedExpression retval = ns.Lookup (ec.DeclContainer, Identifier, loc); if (retval == null) Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", Identifier, ns.FullName); @@ -7010,7 +7053,13 @@ namespace Mono.CSharp { Error (23, "The `.' operator can not be applied to pointer operands (" + TypeManager.CSharpName (expr_type) + ")"); return null; + } else if (expr_type == TypeManager.void_type) { + Error (23, "The `.' operator can not be applied to operands of type 'void'"); + return null; + } else if (expr_type == TypeManager.anonymous_method_type){ + Error (23, "The `.' operator can not be applied to anonymous methods"); } + Expression member_lookup; member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc); @@ -7061,23 +7110,21 @@ namespace Mono.CSharp { return DoResolve (ec, right_side); } - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { return ResolveNamespaceOrType (ec, silent); } - public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent) + public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent) { - FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec, silent); + FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent); - if (new_expr == null) { - Report.Error (234, "No such name or typespace {0}", expr); + if (new_expr == null) return null; - } if (new_expr is Namespace) { Namespace ns = (Namespace) new_expr; - FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc); + FullNamedExpression retval = ns.Lookup (rc.DeclContainer, Identifier, loc); if (!silent && retval == null) Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", Identifier, ns.FullName); @@ -7092,10 +7139,10 @@ namespace Mono.CSharp { return null; } - Expression member_lookup = MemberLookup (ec, expr_type, expr_type, Identifier, loc); + Expression member_lookup = MemberLookup (rc.DeclContainer.TypeBuilder, expr_type, expr_type, Identifier, loc); if (member_lookup == null) { int errors = Report.Errors; - MemberLookupFailed (ec, expr_type, expr_type, Identifier, null, false, loc); + MemberLookupFailed (rc.DeclContainer.TypeBuilder, expr_type, expr_type, Identifier, null, false, loc); if (!silent && errors == Report.Errors) { Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'", @@ -7105,11 +7152,11 @@ namespace Mono.CSharp { } if (!(member_lookup is TypeExpr)) { - new_expr.Error_UnexpectedKind (ec, "type", loc); + new_expr.Error_UnexpectedKind (rc.DeclContainer, "type", loc); return null; } - member_lookup = member_lookup.Resolve (ec, ResolveFlags.Type); + member_lookup = member_lookup.ResolveAsTypeTerminal (rc, silent); return (member_lookup as TypeExpr); } @@ -7342,11 +7389,10 @@ namespace Mono.CSharp { Report.Error (1708, loc, "Fixed size buffers can only be accessed through locals or fields"); return null; } -// TODO: not sure whether it is correct -// if (!ec.InFixedInitializer) { -// Error (1666, "You cannot use fixed sized buffers contained in unfixed expressions. Try using the fixed statement"); -// return null; -// } + if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) { + Error (1666, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); + return null; + } return MakePointerAccess (ec, ff.ElementType); } } @@ -7399,7 +7445,7 @@ namespace Mono.CSharp { Type t = ea.Expr.Type; if (t.GetArrayRank () != ea.Arguments.Count){ Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'", - ea.Arguments.Count, t.GetArrayRank ()); + ea.Arguments.Count.ToString (), t.GetArrayRank ().ToString ()); return null; } @@ -7917,6 +7963,19 @@ namespace Mono.CSharp { public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { + if (right_side == EmptyExpression.OutAccess) { + Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter", + GetSignatureForError ()); + return null; + } + + // if the indexer returns a value type, and we try to set a field in it + if (right_side == EmptyExpression.LValueMemberAccess) { + Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", + GetSignatureForError ()); + return null; + } + ArrayList AllSetters = new ArrayList(); if (!CommonResolve (ec)) return null; @@ -8030,6 +8089,12 @@ namespace Mono.CSharp { { Emit (ec, false); } + + public override string GetSignatureForError () + { + // FIXME: print the argument list of the indexer + return instance_expr.GetSignatureForError () + ".this[...]"; + } } /// @@ -8091,10 +8156,10 @@ namespace Mono.CSharp { return null; } - member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member, + member_lookup = MemberLookup (ec.ContainerType, null, base_type, member, AllMemberTypes, AllBindingFlags, loc); if (member_lookup == null) { - MemberLookupFailed (ec, base_type, base_type, member, null, true, loc); + MemberLookupFailed (ec.ContainerType, base_type, base_type, member, null, true, loc); return null; } @@ -8168,6 +8233,9 @@ namespace Mono.CSharp { public class EmptyExpression : Expression { public static readonly EmptyExpression Null = new EmptyExpression (); + public static readonly EmptyExpression OutAccess = new EmptyExpression (); + public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (); + static EmptyExpression temp = new EmptyExpression (); public static EmptyExpression Grab () { @@ -8284,17 +8352,13 @@ namespace Mono.CSharp { loc = l; } - public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + public override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false); if (lexpr == null) return null; - bool old = ec.TestObsoleteMethodUsage; - ec.TestObsoleteMethodUsage = false; Type ltype = lexpr.ResolveType (ec); - ec.TestObsoleteMethodUsage = old; - if ((ltype == TypeManager.void_type) && (dim != "*")) { Report.Error (1547, Location, "Keyword 'void' cannot be used in this context"); @@ -8310,7 +8374,7 @@ namespace Mono.CSharp { throw new InternalErrorException ("Couldn't create computed type " + ltype + dim); } - if (!ec.InUnsafe && type.IsPointer){ + if (type.IsPointer && !ec.IsInUnsafeScope){ UnsafeError (loc); return null; } @@ -8326,15 +8390,16 @@ namespace Mono.CSharp { } public override string Name { - get { - return left + dim; - } + get { return left + dim; } } public override string FullName { - get { - return type.FullName; - } + get { return type.FullName; } + } + + public override string GetSignatureForError () + { + return left.GetSignatureForError () + dim; } }