Expression ResolveOperator (ResolveContext ec)
		{
			type = expr.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");
			}

			//
			// Step 1: Perform Operator Overload location
			//
			MethodGroupExpr mg;
			string op_name;
			
			if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
				op_name = Operator.GetMetadataName (Operator.OpType.Increment);
			else
				op_name = Operator.GetMetadataName (Operator.OpType.Decrement);

			mg = MemberLookup (ec.Compiler, ec.CurrentType, type, op_name, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;

			if (mg != null) {
				Arguments args = new Arguments (1);
				args.Add (new Argument (expr));
				mg = mg.OverloadResolve (ec, ref args, false, loc);
				if (mg == null)
					return null;

				method = new UserOperatorCall (mg, args, null, loc);
				Convert.ImplicitConversionRequired (ec, method, type, loc);
				return this;
			}

			if (!IsIncrementableNumber (type)) {
				ec.Report.Error (187, loc, "No such operator '" + OperName (mode) + "' defined for type '" +
					   TypeManager.CSharpName (type) + "'");
				return null;
			}

			return this;
		}
		//
		// Performs user-operator overloading
		//
		protected virtual Expression ResolveUserOperator (ResolveContext ec, Type l, Type r)
		{
			Operator user_oper;
			if (oper == Operator.LogicalAnd)
				user_oper = Operator.BitwiseAnd;
			else if (oper == Operator.LogicalOr)
				user_oper = Operator.BitwiseOr;
			else
				user_oper = oper;

			string op = GetOperatorMetadataName (user_oper);

			MethodGroupExpr left_operators = MemberLookup (ec.Compiler, ec.CurrentType, l, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
			MethodGroupExpr right_operators = null;

			if (!TypeManager.IsEqual (r, l)) {
				right_operators = MemberLookup (ec.Compiler, ec.CurrentType, r, op, MemberTypes.Method, AllBindingFlags, loc) as MethodGroupExpr;
				if (right_operators == null && left_operators == null)
					return null;
			} else if (left_operators == null) {
				return null;
			}

			Arguments args = new Arguments (2);
			Argument larg = new Argument (left);
			args.Add (larg);
			Argument rarg = new Argument (right);
			args.Add (rarg);

			MethodGroupExpr union;

			//
			// User-defined operator implementations always take precedence
			// over predefined operator implementations
			//
			if (left_operators != null && right_operators != null) {
				if (IsPredefinedUserOperator (l, user_oper)) {
					union = right_operators.OverloadResolve (ec, ref args, true, loc);
					if (union == null)
						union = left_operators;
				} else if (IsPredefinedUserOperator (r, user_oper)) {
					union = left_operators.OverloadResolve (ec, ref args, true, loc);
					if (union == null)
						union = right_operators;
				} else {
					union = MethodGroupExpr.MakeUnionSet (left_operators, right_operators, loc);
				}
			} else if (left_operators != null) {
				union = left_operators;
			} else {
				union = right_operators;
			}

			union = union.OverloadResolve (ec, ref args, true, loc);
			if (union == null)
				return null;

			Expression oper_expr;

			// TODO: CreateExpressionTree is allocated every time
			if (user_oper != oper) {
				oper_expr = new ConditionalLogicalOperator (union, args, CreateExpressionTree,
					oper == Operator.LogicalAnd, loc).Resolve (ec);
			} else {
				oper_expr = new UserOperatorCall (union, args, CreateExpressionTree, loc);

				//
				// This is used to check if a test 'x == null' can be optimized to a reference equals,
				// and not invoke user operator
				//
				if ((oper & Operator.EqualityMask) != 0) {
					if ((left is NullLiteral && IsBuildInEqualityOperator (r)) ||
						(right is NullLiteral && IsBuildInEqualityOperator (l))) {
						type = TypeManager.bool_type;
						if (left is NullLiteral || right is NullLiteral)
							oper_expr = ReducedExpression.Create (this, oper_expr).Resolve (ec);
					} else if (l != r) {
						MethodInfo mi = (MethodInfo) union;
						
						//
						// Two System.Delegate(s) are never equal
						//
						if (mi.DeclaringType == TypeManager.multicast_delegate_type)
							return null;
					}
				}
			}

			left = larg.Expr;
			right = rarg.Expr;
			return oper_expr;
		}