+ public override void EmitSideEffect (EmitContext ec)
+ {
+ Expr.EmitSideEffect (ec);
+ }
+
+ public static void Error_OperatorCannotBeApplied (Location loc, string oper, Type t)
+ {
+ Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
+ oper, TypeManager.CSharpName (t));
+ }
+
+ static bool IsFloat (Type t)
+ {
+ return t == TypeManager.float_type || t == TypeManager.double_type;
+ }
+
+ //
+ // Returns a stringified representation of the Operator
+ //
+ public static string OperName (Operator oper)
+ {
+ switch (oper) {
+ case Operator.UnaryPlus:
+ return "+";
+ case Operator.UnaryNegation:
+ return "-";
+ case Operator.LogicalNot:
+ return "!";
+ case Operator.OnesComplement:
+ return "~";
+ case Operator.AddressOf:
+ return "&";
+ }
+
+ throw new NotImplementedException (oper.ToString ());
+ }
+
+ Expression ResolveAddressOf (EmitContext ec)
+ {
+ if (!ec.InUnsafe) {
+ UnsafeError (loc);
+ return null;
+ }
+
+ if (!TypeManager.VerifyUnManaged (Expr.Type, loc)) {
+ return null;
+ }
+
+ IVariable variable = Expr as IVariable;
+ bool is_fixed = variable != null && variable.VerifyFixed ();
+
+ if (!ec.InFixedInitializer && !is_fixed) {
+ Error (212, "You can only take the address of unfixed expression inside " +
+ "of a fixed statement initializer");
+ return null;
+ }
+
+ if (ec.InFixedInitializer && is_fixed) {
+ Error (213, "You cannot use the fixed statement to take the address of an already fixed expression");
+ return null;
+ }
+
+ LocalVariableReference lr = Expr as LocalVariableReference;
+ if (lr != null) {
+ if (lr.local_info.IsCaptured) {
+ AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
+ return null;
+ }
+ lr.local_info.AddressTaken = true;
+ lr.local_info.Used = true;
+ }
+
+ ParameterReference pr = Expr as ParameterReference;
+ if ((pr != null) && pr.Parameter.IsCaptured) {
+ AnonymousMethod.Error_AddressOfCapturedVar (pr.Name, loc);
+ return null;
+ }
+
+ // According to the specs, a variable is considered definitely assigned if you take
+ // its address.
+ if ((variable != null) && (variable.VariableInfo != null)) {
+ variable.VariableInfo.SetAssigned (ec);
+ }
+
+ type = TypeManager.GetPointerType (Expr.Type);
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ Expression ResolvePrimitivePredefinedType (Expression expr)
+ {
+ expr = DoNumericPromotion (Oper, expr);
+ Type expr_type = expr.Type;
+ Type[] predefined = predefined_operators [(int) Oper];
+ foreach (Type t in predefined) {
+ if (t == expr_type)
+ return expr;
+ }
+ return null;
+ }
+
+ //
+ // Perform user-operator overload resolution
+ //
+ protected virtual Expression ResolveUserOperator (EmitContext ec, Expression expr)
+ {
+ string op_name = oper_names [(int) Oper];
+ MethodGroupExpr user_op = MemberLookup (ec.ContainerType, expr.Type, op_name, MemberTypes.Method, AllBindingFlags, expr.Location) as MethodGroupExpr;
+ if (user_op == null)
+ return null;
+
+ ArrayList args = new ArrayList (1);
+ args.Add (new Argument (expr));
+ user_op = user_op.OverloadResolve (ec, ref args, false, expr.Location);
+
+ if (user_op == null)
+ return null;
+
+ Expr = ((Argument) args [0]).Expr;
+ return new UserOperatorCall (user_op, args, CreateExpressionTree, expr.Location);
+ }
+
+ //
+ // Unary user type overload resolution
+ //
+ Expression ResolveUserType (EmitContext ec, Expression expr)
+ {
+ Expression best_expr = ResolveUserOperator (ec, expr);
+ if (best_expr != null)
+ return best_expr;
+
+ Type[] predefined = predefined_operators [(int) Oper];
+ foreach (Type t in predefined) {
+ Expression oper_expr = Convert.UserDefinedConversion (ec, expr, t, expr.Location, false);
+ if (oper_expr == null)
+ continue;
+
+ //
+ // decimal type is predefined but has user-operators
+ //
+ if (oper_expr.Type == TypeManager.decimal_type)
+ oper_expr = ResolveUserType (ec, oper_expr);
+ else
+ oper_expr = ResolvePrimitivePredefinedType (oper_expr);
+
+ if (oper_expr == null)
+ continue;
+
+ if (best_expr == null) {
+ best_expr = oper_expr;
+ continue;
+ }
+
+ int result = MethodGroupExpr.BetterTypeConversion (ec, best_expr.Type, t);
+ if (result == 0) {
+ Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'",
+ OperName (Oper), TypeManager.CSharpName (expr.Type));
+ break;
+ }
+
+ if (result == 2)
+ best_expr = oper_expr;
+ }
+
+ if (best_expr == null)
+ return null;
+
+ //
+ // HACK: Decimal user-operator is included in standard operators
+ //
+ if (best_expr.Type == TypeManager.decimal_type)
+ return best_expr;
+
+ Expr = best_expr;
+ type = best_expr.Type;
+ return this;