Inflate custom site container delegates correctly.
[mono.git] / mcs / mcs / expression.cs
index 3bdd95d8332b3a2df2c34fb43c99782f07239e47..ccfb19e030fbbe7eff683e228474a8a2acd59ed0 100644 (file)
@@ -857,7 +857,7 @@ namespace Mono.CSharp {
                        }
 
                        if (expr.Type == TypeManager.void_ptr_type) {
-                               ec.Report.Error (242, loc, "The operation in question is undefined on void pointers");
+                               Error_VoidPointerOperation (ec);
                                return null;
                        }
 
@@ -974,6 +974,8 @@ namespace Mono.CSharp {
                // Holds the real operation
                Expression operation;
 
+               static TypeSpec[] predefined;
+
                public UnaryMutator (Mode m, Expression e, Location loc)
                {
                        mode = m;
@@ -986,6 +988,29 @@ namespace Mono.CSharp {
                        return new SimpleAssign (this, this).CreateExpressionTree (ec);
                }
 
+               void CreatePredefinedOperators ()
+               {
+                       //
+                       // Predefined ++ and -- operators exist for the following types: 
+                       // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal
+                       //
+                       predefined = new TypeSpec[] {
+                               TypeManager.int32_type,
+
+                               TypeManager.sbyte_type,
+                               TypeManager.byte_type,
+                               TypeManager.short_type,
+                               TypeManager.ushort_type,
+                               TypeManager.uint32_type,
+                               TypeManager.int64_type,
+                               TypeManager.uint64_type,
+                               TypeManager.char_type,
+                               TypeManager.float_type,
+                               TypeManager.double_type,
+                               TypeManager.decimal_type
+                       };
+               }
+
                protected override Expression DoResolve (ResolveContext ec)
                {
                        expr = expr.Resolve (ec);
@@ -1011,7 +1036,108 @@ namespace Mono.CSharp {
 
                        eclass = ExprClass.Value;
                        type = expr.Type;
-                       return ResolveOperator (ec);
+
+                       if (expr is RuntimeValueExpression) {
+                               operation = expr;
+                       } else {
+                               // Use itself at the top of the stack
+                               operation = new EmptyExpression (type);
+                       }
+
+                       //
+                       // The operand of the prefix/postfix increment decrement operators
+                       // should be an expression that is classified as a variable,
+                       // a property access or an indexer access
+                       //
+                       // TODO: Move to parser, expr is ATypeNameExpression
+                       if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
+                               expr = expr.ResolveLValue (ec, expr);
+                       } else {
+                               ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
+                       }
+
+                       //
+                       // Step 1: Try to find a user operator, it has priority over predefined ones
+                       //
+                       var user_op = IsDecrement ? Operator.OpType.Decrement : Operator.OpType.Increment;
+                       var methods = MemberCache.GetUserOperator (type, user_op, false);
+
+                       if (methods != null) {
+                               Arguments args = new Arguments (1);
+                               args.Add (new Argument (expr));
+
+                               var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
+                               var method = res.ResolveOperator (ec, ref args);
+                               if (method == null)
+                                       return null;
+
+                               args[0].Expr = operation;
+                               operation = new UserOperatorCall (method, args, null, loc);
+                               operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
+                               return this;
+                       }
+
+                       //
+                       // Step 2: Try predefined types
+                       //
+                       if (predefined == null)
+                               CreatePredefinedOperators ();
+
+                       // Predefined without user conversion first for speed-up
+                       Expression source = null;
+                       bool primitive_type = false;
+                       foreach (var t in predefined) {
+                               if (t == type) {
+                                       source = operation;
+                                       primitive_type = true;
+                                       break;
+                               }
+                       }
+
+                       // ++/-- on pointer variables of all types except void*
+                       if (source == null && type.IsPointer) {
+                               if (type == TypeManager.void_ptr_type) {
+                                       Error_VoidPointerOperation (ec);
+                                       return null;
+                               }
+
+                               source = operation;
+                       }
+
+                       if (source == null) {
+                               // LAMESPEC: It should error on ambiguous operators but that would make us incompatible
+                               foreach (var t in predefined) {
+                                       source = Convert.ImplicitUserConversion (ec, operation, t, loc);
+                                       if (source != null) {
+                                               break;
+                                       }
+                               }
+                       }
+
+                       // ++/-- on enum types
+                       if (source == null && type.IsEnum)
+                               source = operation;
+
+                       if (source == null) {
+                               Unary.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type);
+                               return null;
+                       }
+
+                       var one = new IntConstant (1, loc);
+                       var op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition;
+                       operation = new Binary (op, source, one, loc);
+                       operation = operation.Resolve (ec);
+                       if (operation == null)
+                               throw new NotImplementedException ("should not be reached");
+
+                       if (operation.Type != type) {
+                               if (primitive_type)
+                                       operation = Convert.ExplicitNumericConversion (operation, type);
+                               else
+                                       operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
+                       }
+
+                       return this;
                }
 
                void EmitCode (EmitContext ec, bool is_expr)
@@ -1057,18 +1183,6 @@ namespace Mono.CSharp {
                        get { return (mode & Mode.IsDecrement) != 0; }
                }
 
-               //
-               //   Returns whether an object of type `t' can be incremented
-               //   or decremented with add/sub (ie, basically whether we can
-               //   use pre-post incr-decr operations on it, but it is not a
-               //   System.Decimal, which we require operator overloading to catch)
-               //
-               static bool IsPredefinedOperator (TypeSpec t)
-               {
-                       return (TypeManager.IsPrimitiveType (t) && t != TypeManager.bool_type) ||
-                               TypeManager.IsEnumType (t) ||
-                               t.IsPointer && t != TypeManager.void_ptr_type;
-               }
 
 #if NET_4_0
                public override SLE.Expression MakeExpression (BuilderContext ctx)
@@ -1079,78 +1193,16 @@ namespace Mono.CSharp {
                }
 #endif
 
-               protected override void CloneTo (CloneContext clonectx, Expression t)
+               public static void Reset ()
                {
-                       UnaryMutator target = (UnaryMutator) t;
-
-                       target.expr = expr.Clone (clonectx);
+                       predefined = null;
                }
 
-               Expression ResolveOperator (ResolveContext ec)
+               protected override void CloneTo (CloneContext clonectx, Expression t)
                {
-                       if (expr is RuntimeValueExpression) {
-                               operation = expr;
-                       } else {
-                               // Use itself at the top of the stack
-                               operation = new EmptyExpression (type);
-                       }
-
-                       //
-                       // The operand of the prefix/postfix increment decrement operators
-                       // should be an expression that is classified as a variable,
-                       // a property access or an indexer access
-                       //
-                       if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
-                               expr = expr.ResolveLValue (ec, expr);
-                       } else {
-                               ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
-                       }
-
-                       //
-                       // 1. Check predefined types
-                       //
-                       if (IsPredefinedOperator (type)) {
-                               // TODO: Move to IntConstant once I get rid of int32_type
-                               var one = new IntConstant (1, loc);
-
-                               // TODO: Cache this based on type when using EmptyExpression in
-                               // context cache
-                               Binary.Operator op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition;
-                               operation = new Binary (op, operation, one, loc);
-                               operation = operation.Resolve (ec);
-                               if (operation != null && operation.Type != type)
-                                       operation = Convert.ExplicitNumericConversion (operation, type);
-
-                               return this;
-                       }
-
-                       //
-                       // Step 2: Perform Operator overload resolution
-                       //
-                       var user_op = IsDecrement ? Operator.OpType.Decrement : Operator.OpType.Increment;
-                       var methods = MemberCache.GetUserOperator (type, user_op, false);
-
-                       if (methods != null) {
-                               Arguments args = new Arguments (1);
-                               args.Add (new Argument (expr));
-
-                               var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
-                               var op = res.ResolveOperator (ec, ref args);
-                               if (op == null)
-                                       return null;
-
-                               args[0].Expr = operation;
-                               operation = new UserOperatorCall (op, args, null, loc);
-                               operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
-                               return this;
-                       }
-
-                       string name = IsDecrement ?
-                               Operator.GetName (Operator.OpType.Decrement) :
-                               Operator.GetName (Operator.OpType.Increment);
+                       UnaryMutator target = (UnaryMutator) t;
 
-                       Unary.Error_OperatorCannotBeApplied (ec, loc, name, type);
-                       return null;
+                       target.expr = expr.Clone (clonectx);
                }
        }
 
@@ -1619,7 +1671,7 @@ namespace Mono.CSharp {
                        if (TypeManager.IsReferenceType (type))
                                return new NullConstant (type, loc);
 
-                       Constant c = New.Constantify (type);
+                       Constant c = New.Constantify (type, expr.Location);
                        if (c != null)
                                return c.Resolve (ec);
 
@@ -1698,7 +1750,7 @@ namespace Mono.CSharp {
 
                                var c = b.right as Constant;
                                if (c != null) {
-                                       if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.BitwiseOr || b.oper == Operator.Subtraction))
+                                       if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.Subtraction || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator))))
                                                return ReducedExpression.Create (b.left, b).Resolve (ec);
                                        if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger)
                                                return ReducedExpression.Create (b.left, b).Resolve (ec);
@@ -1707,7 +1759,7 @@ namespace Mono.CSharp {
 
                                c = b.left as Constant;
                                if (c != null) {
-                                       if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.BitwiseOr))
+                                       if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.Subtraction || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator))))
                                                return ReducedExpression.Create (b.right, b).Resolve (ec);
                                        if (b.oper == Operator.Multiply && c.IsOneInteger)
                                                return ReducedExpression.Create (b.right, b).Resolve (ec);
@@ -3274,7 +3326,7 @@ namespace Mono.CSharp {
                        if (oper == Operator.BitwiseAnd || oper == Operator.LogicalAnd) {
                                Constant rc = right as Constant;
                                Constant lc = left as Constant;
-                               if ((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue)) {
+                               if (((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue)) && !(this is Nullable.LiftedBinaryOperator)) {
                                        //
                                        // The result is a constant with side-effect
                                        //
@@ -4042,7 +4094,7 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Variable;
                        
                        if (left.Type == TypeManager.void_ptr_type) {
-                               ec.Report.Error (242, loc, "The operation in question is undefined on void pointers");
+                               Error_VoidPointerOperation (ec);
                                return null;
                        }
                        
@@ -5258,11 +5310,12 @@ namespace Mono.CSharp {
                }
        }
 
-       /// <summary>
-       ///    Implements the new expression 
-       /// </summary>
-       public class New : ExpressionStatement, IMemoryLocation {
-               protected Arguments Arguments;
+       //
+       // Implements simple new expression 
+       //
+       public class New : ExpressionStatement, IMemoryLocation
+       {
+               protected Arguments arguments;
 
                //
                // During bootstrap, it contains the RequestedType,
@@ -5276,45 +5329,63 @@ namespace Mono.CSharp {
                public New (Expression requested_type, Arguments arguments, Location l)
                {
                        RequestedType = requested_type;
-                       Arguments = arguments;
+                       this.arguments = arguments;
                        loc = l;
                }
 
+               #region Properties
+               public Arguments Arguments {
+                       get {
+                               return arguments;
+                       }
+               }
+
+               //
+               // Returns true for resolved `new S()'
+               //
+               public bool IsDefaultStruct {
+                       get {
+                               return arguments == null && type.IsStruct && GetType () == typeof (New);
+                       }
+               }
+
+               #endregion
+
                /// <summary>
                /// Converts complex core type syntax like 'new int ()' to simple constant
                /// </summary>
-               public static Constant Constantify (TypeSpec t)
+               public static Constant Constantify (TypeSpec t, Location loc)
                {
                        if (t == TypeManager.int32_type)
-                               return new IntConstant (0, Location.Null);
+                               return new IntConstant (0, loc);
                        if (t == TypeManager.uint32_type)
-                               return new UIntConstant (0, Location.Null);
+                               return new UIntConstant (0, loc);
                        if (t == TypeManager.int64_type)
-                               return new LongConstant (0, Location.Null);
+                               return new LongConstant (0, loc);
                        if (t == TypeManager.uint64_type)
-                               return new ULongConstant (0, Location.Null);
+                               return new ULongConstant (0, loc);
                        if (t == TypeManager.float_type)
-                               return new FloatConstant (0, Location.Null);
+                               return new FloatConstant (0, loc);
                        if (t == TypeManager.double_type)
-                               return new DoubleConstant (0, Location.Null);
+                               return new DoubleConstant (0, loc);
                        if (t == TypeManager.short_type)
-                               return new ShortConstant (0, Location.Null);
+                               return new ShortConstant (0, loc);
                        if (t == TypeManager.ushort_type)
-                               return new UShortConstant (0, Location.Null);
+                               return new UShortConstant (0, loc);
                        if (t == TypeManager.sbyte_type)
-                               return new SByteConstant (0, Location.Null);
+                               return new SByteConstant (0, loc);
                        if (t == TypeManager.byte_type)
-                               return new ByteConstant (0, Location.Null);
+                               return new ByteConstant (0, loc);
                        if (t == TypeManager.char_type)
-                               return new CharConstant ('\0', Location.Null);
+                               return new CharConstant ('\0', loc);
                        if (t == TypeManager.bool_type)
-                               return new BoolConstant (false, Location.Null);
+                               return new BoolConstant (false, loc);
                        if (t == TypeManager.decimal_type)
-                               return new DecimalConstant (0, Location.Null);
+                               return new DecimalConstant (0, loc);
                        if (TypeManager.IsEnumType (t))
-                               return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t)), t);
+                               return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t), loc), t);
                        if (TypeManager.IsNullableType (t))
-                               return Nullable.LiftedNull.Create (t, Location.Null);
+                               return Nullable.LiftedNull.Create (t, loc);
 
                        return null;
                }
@@ -5337,7 +5408,7 @@ namespace Mono.CSharp {
                        if (real_class == null)
                                return null;
 
-                       New proxy = new New (new TypeExpression (real_class, loc), Arguments, loc);
+                       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);
                }
@@ -5350,7 +5421,7 @@ namespace Mono.CSharp {
                                args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
                        } else {
                                args = Arguments.CreateForExpressionTree (ec,
-                                       Arguments, new TypeOfMethod (method, loc));
+                                       arguments, new TypeOfMethod (method, loc));
                        }
 
                        return CreateExpressionFactoryCall (ec, "New", args);
@@ -5371,14 +5442,14 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       if (Arguments == null) {
-                               Constant c = Constantify (type);
+                       if (arguments == null) {
+                               Constant c = Constantify (type, RequestedType.Location);
                                if (c != null)
                                        return ReducedExpression.Create (c.Resolve (ec), this);
                        }
 
                        if (TypeManager.IsDelegateType (type)) {
-                               return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
+                               return (new NewDelegate (type, arguments, loc)).Resolve (ec);
                        }
 
                        var tparam = type as TypeParameterSpec;
@@ -5389,7 +5460,7 @@ namespace Mono.CSharp {
                                                TypeManager.CSharpName (type));
                                }
 
-                               if ((Arguments != null) && (Arguments.Count != 0)) {
+                               if ((arguments != null) && (arguments.Count != 0)) {
                                        ec.Report.Error (417, loc,
                                                "`{0}': cannot provide arguments when creating an instance of a variable type",
                                                TypeManager.CSharpName (type));
@@ -5427,21 +5498,21 @@ namespace Mono.CSharp {
                        //
                        // Any struct always defines parameterless constructor
                        //
-                       if (type.IsStruct && Arguments == null)
+                       if (type.IsStruct && arguments == null)
                                return this;
 
                        bool dynamic;
-                       if (Arguments != null) {
-                               Arguments.Resolve (ec, out dynamic);
+                       if (arguments != null) {
+                               arguments.Resolve (ec, out dynamic);
                        } else {
                                dynamic = false;
                        }
 
-                       method = ConstructorLookup (ec, type, ref Arguments, loc);
+                       method = ConstructorLookup (ec, type, ref arguments, loc);
 
                        if (dynamic) {
-                               Arguments.Insert (0, new Argument (new TypeOf (texpr, loc).Resolve (ec), Argument.AType.DynamicTypeName));
-                               return new DynamicConstructorBinder (type, Arguments, loc).Resolve (ec);
+                               arguments.Insert (0, new Argument (new TypeOf (texpr, loc).Resolve (ec), Argument.AType.DynamicTypeName));
+                               return new DynamicConstructorBinder (type, arguments, loc).Resolve (ec);
                        }
 
                        return this;
@@ -5522,8 +5593,8 @@ namespace Mono.CSharp {
                                vr.EmitLoad (ec);
                        }
                        
-                       if (Arguments != null)
-                               Arguments.Emit (ec);
+                       if (arguments != null)
+                               arguments.Emit (ec);
 
                        if (is_value_type) {
                                if (method == null) {
@@ -5568,12 +5639,6 @@ namespace Mono.CSharp {
                                ec.Emit (OpCodes.Pop);
                }
 
-               public virtual bool HasInitializer {
-                       get {
-                               return false;
-                       }
-               }
-
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        EmitAddressOf (ec, mode);
@@ -5605,8 +5670,8 @@ namespace Mono.CSharp {
                        if (method == null) {
                                ec.Emit (OpCodes.Initobj, type);
                        } else {
-                               if (Arguments != null)
-                                       Arguments.Emit (ec);
+                               if (arguments != null)
+                                       arguments.Emit (ec);
 
                                ec.Emit (OpCodes.Call, method);
                        }
@@ -5620,14 +5685,14 @@ namespace Mono.CSharp {
                        New target = (New) t;
 
                        target.RequestedType = RequestedType.Clone (clonectx);
-                       if (Arguments != null){
-                               target.Arguments = Arguments.Clone (clonectx);
+                       if (arguments != null){
+                               target.arguments = arguments.Clone (clonectx);
                        }
                }
 
                public override SLE.Expression MakeExpression (BuilderContext ctx)
                {
-                       return SLE.Expression.New ((ConstructorInfo) method.GetMetaInfo (), Arguments.MakeExpression (Arguments, ctx));
+                       return SLE.Expression.New ((ConstructorInfo) method.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx));
                }
        }
 
@@ -9234,12 +9299,6 @@ namespace Mono.CSharp {
 
                        return left_on_stack;
                }
-
-               public override bool HasInitializer {
-                       get {
-                               return !initializers.IsEmpty;
-                       }
-               }
        }
 
        public class NewAnonymousType : New
@@ -9299,8 +9358,8 @@ namespace Mono.CSharp {
                        foreach (Property p in anonymous_type.Properties)
                                init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc));
 
-                       var ctor_args = new ArrayInitializer (Arguments.Count, loc);
-                       foreach (Argument a in Arguments)
+                       var ctor_args = new ArrayInitializer (arguments.Count, loc);
+                       foreach (Argument a in arguments)
                                ctor_args.Add (a.CreateExpressionTree (ec));
 
                        Arguments args = new Arguments (3);
@@ -9325,7 +9384,7 @@ namespace Mono.CSharp {
                        }
 
                        bool error = false;
-                       Arguments = new Arguments (parameters.Count);
+                       arguments = new Arguments (parameters.Count);
                        TypeExpression [] t_args = new TypeExpression [parameters.Count];
                        for (int i = 0; i < parameters.Count; ++i) {
                                Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec);
@@ -9334,7 +9393,7 @@ namespace Mono.CSharp {
                                        continue;
                                }
 
-                               Arguments.Add (new Argument (e));
+                               arguments.Add (new Argument (e));
                                t_args [i] = new TypeExpression (e.Type, e.Location);
                        }