~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/expression.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// expression.cs: Expression representation for the IL tree.
 
3
//
 
4
// Author:
 
5
//   Miguel de Icaza (miguel@ximian.com)
 
6
//   Marek Safar (marek.safar@gmail.com)
 
7
//
 
8
// Copyright 2001, 2002, 2003 Ximian, Inc.
 
9
// Copyright 2003-2008 Novell, Inc.
 
10
//
 
11
 
 
12
using System;
 
13
using System.Collections.Generic;
 
14
using System.Linq;
 
15
using SLE = System.Linq.Expressions;
 
16
 
 
17
#if STATIC
 
18
using MetaType = IKVM.Reflection.Type;
 
19
using IKVM.Reflection;
 
20
using IKVM.Reflection.Emit;
 
21
#else
 
22
using MetaType = System.Type;
 
23
using System.Reflection;
 
24
using System.Reflection.Emit;
 
25
#endif
 
26
 
 
27
namespace Mono.CSharp
 
28
{
 
29
        //
 
30
        // This is an user operator expression, automatically created during
 
31
        // resolve phase
 
32
        //
 
33
        public class UserOperatorCall : Expression {
 
34
                protected readonly Arguments arguments;
 
35
                protected readonly MethodSpec oper;
 
36
                readonly Func<ResolveContext, Expression, Expression> expr_tree;
 
37
 
 
38
                public UserOperatorCall (MethodSpec oper, Arguments args, Func<ResolveContext, Expression, Expression> expr_tree, Location loc)
 
39
                {
 
40
                        this.oper = oper;
 
41
                        this.arguments = args;
 
42
                        this.expr_tree = expr_tree;
 
43
 
 
44
                        type = oper.ReturnType;
 
45
                        eclass = ExprClass.Value;
 
46
                        this.loc = loc;
 
47
                }
 
48
 
 
49
                public override Expression CreateExpressionTree (ResolveContext ec)
 
50
                {
 
51
                        if (expr_tree != null)
 
52
                                return expr_tree (ec, new TypeOfMethod (oper, loc));
 
53
 
 
54
                        Arguments args = Arguments.CreateForExpressionTree (ec, arguments,
 
55
                                new NullLiteral (loc),
 
56
                                new TypeOfMethod (oper, loc));
 
57
 
 
58
                        return CreateExpressionFactoryCall (ec, "Call", args);
 
59
                }
 
60
 
 
61
                protected override void CloneTo (CloneContext context, Expression target)
 
62
                {
 
63
                        // Nothing to clone
 
64
                }
 
65
                
 
66
                protected override Expression DoResolve (ResolveContext ec)
 
67
                {
 
68
                        //
 
69
                        // We are born fully resolved
 
70
                        //
 
71
                        return this;
 
72
                }
 
73
 
 
74
                public override void Emit (EmitContext ec)
 
75
                {
 
76
                        Invocation.EmitCall (ec, null, oper, arguments, loc);
 
77
                }
 
78
 
 
79
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
80
                {
 
81
#if STATIC
 
82
                        return base.MakeExpression (ctx);
 
83
#else
 
84
                        return SLE.Expression.Call ((MethodInfo) oper.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx));
 
85
#endif
 
86
                }
 
87
        }
 
88
 
 
89
        public class ParenthesizedExpression : ShimExpression
 
90
        {
 
91
                public ParenthesizedExpression (Expression expr)
 
92
                        : base (expr)
 
93
                {
 
94
                        loc = expr.Location;
 
95
                }
 
96
 
 
97
                protected override Expression DoResolve (ResolveContext ec)
 
98
                {
 
99
                        return expr.Resolve (ec);
 
100
                }
 
101
 
 
102
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
103
                {
 
104
                        return expr.DoResolveLValue (ec, right_side);
 
105
                }
 
106
                
 
107
                public override object Accept (StructuralVisitor visitor)
 
108
                {
 
109
                        return visitor.Visit (this);
 
110
                }
 
111
        }
 
112
        
 
113
        //
 
114
        //   Unary implements unary expressions.
 
115
        //
 
116
        public class Unary : Expression
 
117
        {
 
118
                public enum Operator : byte {
 
119
                        UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
 
120
                        AddressOf,  TOP
 
121
                }
 
122
 
 
123
                public readonly Operator Oper;
 
124
                public Expression Expr;
 
125
                Expression enum_conversion;
 
126
 
 
127
                public Unary (Operator op, Expression expr, Location loc)
 
128
                {
 
129
                        Oper = op;
 
130
                        Expr = expr;
 
131
                        this.loc = loc;
 
132
                }
 
133
 
 
134
                // <summary>
 
135
                //   This routine will attempt to simplify the unary expression when the
 
136
                //   argument is a constant.
 
137
                // </summary>
 
138
                Constant TryReduceConstant (ResolveContext ec, Constant e)
 
139
                {
 
140
                        if (e is EmptyConstantCast)
 
141
                                return TryReduceConstant (ec, ((EmptyConstantCast) e).child);
 
142
                        
 
143
                        if (e is SideEffectConstant) {
 
144
                                Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value);
 
145
                                return r == null ? null : new SideEffectConstant (r, e, r.Location);
 
146
                        }
 
147
 
 
148
                        TypeSpec expr_type = e.Type;
 
149
                        
 
150
                        switch (Oper){
 
151
                        case Operator.UnaryPlus:
 
152
                                // Unary numeric promotions
 
153
                                switch (expr_type.BuiltinType) {
 
154
                                case BuiltinTypeSpec.Type.Byte:
 
155
                                        return new IntConstant (ec.BuiltinTypes, ((ByteConstant) e).Value, e.Location);
 
156
                                case BuiltinTypeSpec.Type.SByte:
 
157
                                        return new IntConstant (ec.BuiltinTypes, ((SByteConstant) e).Value, e.Location);
 
158
                                case BuiltinTypeSpec.Type.Short:
 
159
                                        return new IntConstant (ec.BuiltinTypes, ((ShortConstant) e).Value, e.Location);
 
160
                                case BuiltinTypeSpec.Type.UShort:
 
161
                                        return new IntConstant (ec.BuiltinTypes, ((UShortConstant) e).Value, e.Location);
 
162
                                case BuiltinTypeSpec.Type.Char:
 
163
                                        return new IntConstant (ec.BuiltinTypes, ((CharConstant) e).Value, e.Location);
 
164
                                
 
165
                                // Predefined operators
 
166
                                case BuiltinTypeSpec.Type.Int:
 
167
                                case BuiltinTypeSpec.Type.UInt:
 
168
                                case BuiltinTypeSpec.Type.Long:
 
169
                                case BuiltinTypeSpec.Type.ULong:
 
170
                                case BuiltinTypeSpec.Type.Float:
 
171
                                case BuiltinTypeSpec.Type.Double:
 
172
                                case BuiltinTypeSpec.Type.Decimal:
 
173
                                        return e;
 
174
                                }
 
175
                                
 
176
                                return null;
 
177
                                
 
178
                        case Operator.UnaryNegation:
 
179
                                // Unary numeric promotions
 
180
                                switch (expr_type.BuiltinType) {
 
181
                                case BuiltinTypeSpec.Type.Byte:
 
182
                                        return new IntConstant (ec.BuiltinTypes, -((ByteConstant) e).Value, e.Location);
 
183
                                case BuiltinTypeSpec.Type.SByte:
 
184
                                        return new IntConstant (ec.BuiltinTypes, -((SByteConstant) e).Value, e.Location);
 
185
                                case BuiltinTypeSpec.Type.Short:
 
186
                                        return new IntConstant (ec.BuiltinTypes, -((ShortConstant) e).Value, e.Location);
 
187
                                case BuiltinTypeSpec.Type.UShort:
 
188
                                        return new IntConstant (ec.BuiltinTypes, -((UShortConstant) e).Value, e.Location);
 
189
                                case BuiltinTypeSpec.Type.Char:
 
190
                                        return new IntConstant (ec.BuiltinTypes, -((CharConstant) e).Value, e.Location);
 
191
 
 
192
                                // Predefined operators
 
193
                                case BuiltinTypeSpec.Type.Int:
 
194
                                        int ivalue = ((IntConstant) e).Value;
 
195
                                        if (ivalue == int.MinValue) {
 
196
                                                if (ec.ConstantCheckState) {
 
197
                                                        ConstantFold.Error_CompileTimeOverflow (ec, loc);
 
198
                                                        return null;
 
199
                                                }
 
200
                                                return e;
 
201
                                        }
 
202
                                        return new IntConstant (ec.BuiltinTypes, -ivalue, e.Location);
 
203
 
 
204
                                case BuiltinTypeSpec.Type.Long:
 
205
                                        long lvalue = ((LongConstant) e).Value;
 
206
                                        if (lvalue == long.MinValue) {
 
207
                                                if (ec.ConstantCheckState) {
 
208
                                                        ConstantFold.Error_CompileTimeOverflow (ec, loc);
 
209
                                                        return null;
 
210
                                                }
 
211
                                                return e;
 
212
                                        }
 
213
                                        return new LongConstant (ec.BuiltinTypes, -lvalue, e.Location);
 
214
 
 
215
                                case BuiltinTypeSpec.Type.UInt:
 
216
                                        UIntLiteral uil = e as UIntLiteral;
 
217
                                        if (uil != null) {
 
218
                                                if (uil.Value == int.MaxValue + (uint) 1)
 
219
                                                        return new IntLiteral (ec.BuiltinTypes, int.MinValue, e.Location);
 
220
                                                return new LongLiteral (ec.BuiltinTypes, -uil.Value, e.Location);
 
221
                                        }
 
222
                                        return new LongConstant (ec.BuiltinTypes, -((UIntConstant) e).Value, e.Location);
 
223
 
 
224
 
 
225
                                case BuiltinTypeSpec.Type.ULong:
 
226
                                        ULongLiteral ull = e as ULongLiteral;
 
227
                                        if (ull != null && ull.Value == 9223372036854775808)
 
228
                                                return new LongLiteral (ec.BuiltinTypes, long.MinValue, e.Location);
 
229
                                        return null;
 
230
 
 
231
                                case BuiltinTypeSpec.Type.Float:
 
232
                                        FloatLiteral fl = e as FloatLiteral;
 
233
                                        // For better error reporting
 
234
                                        if (fl != null)
 
235
                                                return new FloatLiteral (ec.BuiltinTypes, -fl.Value, e.Location);
 
236
 
 
237
                                        return new FloatConstant (ec.BuiltinTypes, -((FloatConstant) e).Value, e.Location);
 
238
 
 
239
                                case BuiltinTypeSpec.Type.Double:
 
240
                                        DoubleLiteral dl = e as DoubleLiteral;
 
241
                                        // For better error reporting
 
242
                                        if (dl != null)
 
243
                                                return new DoubleLiteral (ec.BuiltinTypes, -dl.Value, e.Location);
 
244
 
 
245
                                        return new DoubleConstant (ec.BuiltinTypes, -((DoubleConstant) e).Value, e.Location);
 
246
 
 
247
                                case BuiltinTypeSpec.Type.Decimal:
 
248
                                        return new DecimalConstant (ec.BuiltinTypes, -((DecimalConstant) e).Value, e.Location);
 
249
                                }
 
250
 
 
251
                                return null;
 
252
                                
 
253
                        case Operator.LogicalNot:
 
254
                                if (expr_type.BuiltinType != BuiltinTypeSpec.Type.Bool)
 
255
                                        return null;
 
256
                                
 
257
                                bool b = (bool)e.GetValue ();
 
258
                                return new BoolConstant (ec.BuiltinTypes, !b, e.Location);
 
259
                                
 
260
                        case Operator.OnesComplement:
 
261
                                // Unary numeric promotions
 
262
                                switch (expr_type.BuiltinType) {
 
263
                                case BuiltinTypeSpec.Type.Byte:
 
264
                                        return new IntConstant (ec.BuiltinTypes, ~((ByteConstant) e).Value, e.Location);
 
265
                                case BuiltinTypeSpec.Type.SByte:
 
266
                                        return new IntConstant (ec.BuiltinTypes, ~((SByteConstant) e).Value, e.Location);
 
267
                                case BuiltinTypeSpec.Type.Short:
 
268
                                        return new IntConstant (ec.BuiltinTypes, ~((ShortConstant) e).Value, e.Location);
 
269
                                case BuiltinTypeSpec.Type.UShort:
 
270
                                        return new IntConstant (ec.BuiltinTypes, ~((UShortConstant) e).Value, e.Location);
 
271
                                case BuiltinTypeSpec.Type.Char:
 
272
                                        return new IntConstant (ec.BuiltinTypes, ~((CharConstant) e).Value, e.Location);
 
273
                                
 
274
                                // Predefined operators
 
275
                                case BuiltinTypeSpec.Type.Int:
 
276
                                        return new IntConstant (ec.BuiltinTypes, ~((IntConstant)e).Value, e.Location);
 
277
                                case BuiltinTypeSpec.Type.UInt:
 
278
                                        return new UIntConstant (ec.BuiltinTypes, ~((UIntConstant) e).Value, e.Location);
 
279
                                case BuiltinTypeSpec.Type.Long:
 
280
                                        return new LongConstant (ec.BuiltinTypes, ~((LongConstant) e).Value, e.Location);
 
281
                                case BuiltinTypeSpec.Type.ULong:
 
282
                                        return new ULongConstant (ec.BuiltinTypes, ~((ULongConstant) e).Value, e.Location);
 
283
                                }
 
284
                                if (e is EnumConstant) {
 
285
                                        e = TryReduceConstant (ec, ((EnumConstant)e).Child);
 
286
                                        if (e != null)
 
287
                                                e = new EnumConstant (e, expr_type);
 
288
                                        return e;
 
289
                                }
 
290
                                return null;
 
291
                        }
 
292
                        throw new Exception ("Can not constant fold: " + Oper.ToString());
 
293
                }
 
294
                
 
295
                protected virtual Expression ResolveOperator (ResolveContext ec, Expression expr)
 
296
                {
 
297
                        eclass = ExprClass.Value;
 
298
 
 
299
                        TypeSpec expr_type = expr.Type;
 
300
                        Expression best_expr;
 
301
 
 
302
                        TypeSpec[] predefined = ec.BuiltinTypes.OperatorsUnary [(int) Oper];
 
303
 
 
304
                        //
 
305
                        // Primitive types first
 
306
                        //
 
307
                        if (BuiltinTypeSpec.IsPrimitiveType (expr_type)) {
 
308
                                best_expr = ResolvePrimitivePredefinedType (ec, expr, predefined);
 
309
                                if (best_expr == null)
 
310
                                        return null;
 
311
 
 
312
                                type = best_expr.Type;
 
313
                                Expr = best_expr;
 
314
                                return this;
 
315
                        }
 
316
 
 
317
                        //
 
318
                        // E operator ~(E x);
 
319
                        //
 
320
                        if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type))
 
321
                                return ResolveEnumOperator (ec, expr, predefined);
 
322
 
 
323
                        return ResolveUserType (ec, expr, predefined);
 
324
                }
 
325
 
 
326
                protected virtual Expression ResolveEnumOperator (ResolveContext ec, Expression expr, TypeSpec[] predefined)
 
327
                {
 
328
                        TypeSpec underlying_type = EnumSpec.GetUnderlyingType (expr.Type);
 
329
                        Expression best_expr = ResolvePrimitivePredefinedType (ec, EmptyCast.Create (expr, underlying_type), predefined);
 
330
                        if (best_expr == null)
 
331
                                return null;
 
332
 
 
333
                        Expr = best_expr;
 
334
                        enum_conversion = Convert.ExplicitNumericConversion (ec, new EmptyExpression (best_expr.Type), underlying_type);
 
335
                        type = expr.Type;
 
336
                        return EmptyCast.Create (this, type);
 
337
                }
 
338
 
 
339
                public override Expression CreateExpressionTree (ResolveContext ec)
 
340
                {
 
341
                        return CreateExpressionTree (ec, null);
 
342
                }
 
343
 
 
344
                Expression CreateExpressionTree (ResolveContext ec, Expression user_op)
 
345
                {
 
346
                        string method_name;
 
347
                        switch (Oper) {
 
348
                        case Operator.AddressOf:
 
349
                                Error_PointerInsideExpressionTree (ec);
 
350
                                return null;
 
351
                        case Operator.UnaryNegation:
 
352
                                if (ec.HasSet (ResolveContext.Options.CheckedScope) && user_op == null && !IsFloat (type))
 
353
                                        method_name = "NegateChecked";
 
354
                                else
 
355
                                        method_name = "Negate";
 
356
                                break;
 
357
                        case Operator.OnesComplement:
 
358
                        case Operator.LogicalNot:
 
359
                                method_name = "Not";
 
360
                                break;
 
361
                        case Operator.UnaryPlus:
 
362
                                method_name = "UnaryPlus";
 
363
                                break;
 
364
                        default:
 
365
                                throw new InternalErrorException ("Unknown unary operator " + Oper.ToString ());
 
366
                        }
 
367
 
 
368
                        Arguments args = new Arguments (2);
 
369
                        args.Add (new Argument (Expr.CreateExpressionTree (ec)));
 
370
                        if (user_op != null)
 
371
                                args.Add (new Argument (user_op));
 
372
 
 
373
                        return CreateExpressionFactoryCall (ec, method_name, args);
 
374
                }
 
375
 
 
376
                public static TypeSpec[][] CreatePredefinedOperatorsTable (BuiltinTypes types)
 
377
                {
 
378
                        var predefined_operators = new TypeSpec[(int) Operator.TOP][];
 
379
 
 
380
                        //
 
381
                        // 7.6.1 Unary plus operator
 
382
                        //
 
383
                        predefined_operators [(int) Operator.UnaryPlus] = new TypeSpec [] {
 
384
                                types.Int, types.UInt,
 
385
                                types.Long, types.ULong,
 
386
                                types.Float, types.Double,
 
387
                                types.Decimal
 
388
                        };
 
389
 
 
390
                        //
 
391
                        // 7.6.2 Unary minus operator
 
392
                        //
 
393
                        predefined_operators [(int) Operator.UnaryNegation] = new TypeSpec [] {
 
394
                                types.Int,  types.Long,
 
395
                                types.Float, types.Double,
 
396
                                types.Decimal
 
397
                        };
 
398
 
 
399
                        //
 
400
                        // 7.6.3 Logical negation operator
 
401
                        //
 
402
                        predefined_operators [(int) Operator.LogicalNot] = new TypeSpec [] {
 
403
                                types.Bool
 
404
                        };
 
405
 
 
406
                        //
 
407
                        // 7.6.4 Bitwise complement operator
 
408
                        //
 
409
                        predefined_operators [(int) Operator.OnesComplement] = new TypeSpec [] {
 
410
                                types.Int, types.UInt,
 
411
                                types.Long, types.ULong
 
412
                        };
 
413
 
 
414
                        return predefined_operators;
 
415
                }
 
416
 
 
417
                //
 
418
                // Unary numeric promotions
 
419
                //
 
420
                static Expression DoNumericPromotion (ResolveContext rc, Operator op, Expression expr)
 
421
                {
 
422
                        TypeSpec expr_type = expr.Type;
 
423
                        if (op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) {
 
424
                                switch (expr_type.BuiltinType) {
 
425
                                case BuiltinTypeSpec.Type.Byte:
 
426
                                case BuiltinTypeSpec.Type.SByte:
 
427
                                case BuiltinTypeSpec.Type.Short:
 
428
                                case BuiltinTypeSpec.Type.UShort:
 
429
                                case BuiltinTypeSpec.Type.Char:
 
430
                                        return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Int);
 
431
                                }
 
432
                        }
 
433
 
 
434
                        if (op == Operator.UnaryNegation && expr_type.BuiltinType == BuiltinTypeSpec.Type.UInt)
 
435
                                return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Long);
 
436
 
 
437
                        return expr;
 
438
                }
 
439
 
 
440
                protected override Expression DoResolve (ResolveContext ec)
 
441
                {
 
442
                        if (Oper == Operator.AddressOf) {
 
443
                                return ResolveAddressOf (ec);
 
444
                        }
 
445
 
 
446
                        Expr = Expr.Resolve (ec);
 
447
                        if (Expr == null)
 
448
                                return null;
 
449
 
 
450
                        if (Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
451
                                Arguments args = new Arguments (1);
 
452
                                args.Add (new Argument (Expr));
 
453
                                return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).Resolve (ec);
 
454
                        }
 
455
 
 
456
                        if (Expr.Type.IsNullableType)
 
457
                                return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec);
 
458
 
 
459
                        //
 
460
                        // Attempt to use a constant folding operation.
 
461
                        //
 
462
                        Constant cexpr = Expr as Constant;
 
463
                        if (cexpr != null) {
 
464
                                cexpr = TryReduceConstant (ec, cexpr);
 
465
                                if (cexpr != null)
 
466
                                        return cexpr;
 
467
                        }
 
468
 
 
469
                        Expression expr = ResolveOperator (ec, Expr);
 
470
                        if (expr == null)
 
471
                                Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), Expr.Type);
 
472
                        
 
473
                        //
 
474
                        // Reduce unary operator on predefined types
 
475
                        //
 
476
                        if (expr == this && Oper == Operator.UnaryPlus)
 
477
                                return Expr;
 
478
 
 
479
                        return expr;
 
480
                }
 
481
 
 
482
                public override Expression DoResolveLValue (ResolveContext ec, Expression right)
 
483
                {
 
484
                        return null;
 
485
                }
 
486
 
 
487
                public override void Emit (EmitContext ec)
 
488
                {
 
489
                        EmitOperator (ec, type);
 
490
                }
 
491
 
 
492
                protected void EmitOperator (EmitContext ec, TypeSpec type)
 
493
                {
 
494
                        switch (Oper) {
 
495
                        case Operator.UnaryPlus:
 
496
                                Expr.Emit (ec);
 
497
                                break;
 
498
                                
 
499
                        case Operator.UnaryNegation:
 
500
                                if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) {
 
501
                                        ec.Emit (OpCodes.Ldc_I4_0);
 
502
                                        if (type.BuiltinType == BuiltinTypeSpec.Type.Long)
 
503
                                                ec.Emit (OpCodes.Conv_U8);
 
504
                                        Expr.Emit (ec);
 
505
                                        ec.Emit (OpCodes.Sub_Ovf);
 
506
                                } else {
 
507
                                        Expr.Emit (ec);
 
508
                                        ec.Emit (OpCodes.Neg);
 
509
                                }
 
510
                                
 
511
                                break;
 
512
                                
 
513
                        case Operator.LogicalNot:
 
514
                                Expr.Emit (ec);
 
515
                                ec.Emit (OpCodes.Ldc_I4_0);
 
516
                                ec.Emit (OpCodes.Ceq);
 
517
                                break;
 
518
                                
 
519
                        case Operator.OnesComplement:
 
520
                                Expr.Emit (ec);
 
521
                                ec.Emit (OpCodes.Not);
 
522
                                break;
 
523
                                
 
524
                        case Operator.AddressOf:
 
525
                                ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
 
526
                                break;
 
527
                                
 
528
                        default:
 
529
                                throw new Exception ("This should not happen: Operator = "
 
530
                                                     + Oper.ToString ());
 
531
                        }
 
532
 
 
533
                        //
 
534
                        // Same trick as in Binary expression
 
535
                        //
 
536
                        if (enum_conversion != null)
 
537
                                enum_conversion.Emit (ec);
 
538
                }
 
539
 
 
540
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 
541
                {
 
542
                        if (Oper == Operator.LogicalNot)
 
543
                                Expr.EmitBranchable (ec, target, !on_true);
 
544
                        else
 
545
                                base.EmitBranchable (ec, target, on_true);
 
546
                }
 
547
 
 
548
                public override void EmitSideEffect (EmitContext ec)
 
549
                {
 
550
                        Expr.EmitSideEffect (ec);
 
551
                }
 
552
 
 
553
                public static void Error_OperatorCannotBeApplied (ResolveContext ec, Location loc, string oper, TypeSpec t)
 
554
                {
 
555
                        ec.Report.Error (23, loc, "The `{0}' operator cannot be applied to operand of type `{1}'",
 
556
                                oper, TypeManager.CSharpName (t));
 
557
                }
 
558
 
 
559
                //
 
560
                // Converts operator to System.Linq.Expressions.ExpressionType enum name
 
561
                //
 
562
                string GetOperatorExpressionTypeName ()
 
563
                {
 
564
                        switch (Oper) {
 
565
                        case Operator.OnesComplement:
 
566
                                return "OnesComplement";
 
567
                        case Operator.LogicalNot:
 
568
                                return "Not";
 
569
                        case Operator.UnaryNegation:
 
570
                                return "Negate";
 
571
                        case Operator.UnaryPlus:
 
572
                                return "UnaryPlus";
 
573
                        default:
 
574
                                throw new NotImplementedException ("Unknown express type operator " + Oper.ToString ());
 
575
                        }
 
576
                }
 
577
 
 
578
                static bool IsFloat (TypeSpec t)
 
579
                {
 
580
                        return t.BuiltinType == BuiltinTypeSpec.Type.Double || t.BuiltinType == BuiltinTypeSpec.Type.Float;
 
581
                }
 
582
 
 
583
                //
 
584
                // Returns a stringified representation of the Operator
 
585
                //
 
586
                public static string OperName (Operator oper)
 
587
                {
 
588
                        switch (oper) {
 
589
                        case Operator.UnaryPlus:
 
590
                                return "+";
 
591
                        case Operator.UnaryNegation:
 
592
                                return "-";
 
593
                        case Operator.LogicalNot:
 
594
                                return "!";
 
595
                        case Operator.OnesComplement:
 
596
                                return "~";
 
597
                        case Operator.AddressOf:
 
598
                                return "&";
 
599
                        }
 
600
 
 
601
                        throw new NotImplementedException (oper.ToString ());
 
602
                }
 
603
 
 
604
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
605
                {
 
606
                        var expr = Expr.MakeExpression (ctx);
 
607
                        bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
 
608
 
 
609
                        switch (Oper) {
 
610
                        case Operator.UnaryNegation:
 
611
                                return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr);
 
612
                        case Operator.LogicalNot:
 
613
                                return SLE.Expression.Not (expr);
 
614
#if NET_4_0
 
615
                        case Operator.OnesComplement:
 
616
                                return SLE.Expression.OnesComplement (expr);
 
617
#endif
 
618
                        default:
 
619
                                throw new NotImplementedException (Oper.ToString ());
 
620
                        }
 
621
                }
 
622
 
 
623
                Expression ResolveAddressOf (ResolveContext ec)
 
624
                {
 
625
                        if (!ec.IsUnsafe)
 
626
                                UnsafeError (ec, loc);
 
627
 
 
628
                        Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress);
 
629
                        if (Expr == null || Expr.eclass != ExprClass.Variable) {
 
630
                                ec.Report.Error (211, loc, "Cannot take the address of the given expression");
 
631
                                return null;
 
632
                        }
 
633
 
 
634
                        if (!TypeManager.VerifyUnmanaged (ec.Module, Expr.Type, loc)) {
 
635
                                return null;
 
636
                        }
 
637
 
 
638
                        IVariableReference vr = Expr as IVariableReference;
 
639
                        bool is_fixed;
 
640
                        if (vr != null) {
 
641
                                VariableInfo vi = vr.VariableInfo;
 
642
                                if (vi != null) {
 
643
                                        if (vi.LocalInfo != null)
 
644
                                                vi.LocalInfo.SetIsUsed ();
 
645
 
 
646
                                        //
 
647
                                        // A variable is considered definitely assigned if you take its address.
 
648
                                        //
 
649
                                        vi.SetAssigned (ec);
 
650
                                }
 
651
 
 
652
                                is_fixed = vr.IsFixed;
 
653
                                vr.SetHasAddressTaken ();
 
654
 
 
655
                                if (vr.IsHoisted) {
 
656
                                        AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc);
 
657
                                }
 
658
                        } else {
 
659
                                IFixedExpression fe = Expr as IFixedExpression;
 
660
                                is_fixed = fe != null && fe.IsFixed;
 
661
                        }
 
662
 
 
663
                        if (!is_fixed && !ec.HasSet (ResolveContext.Options.FixedInitializerScope)) {
 
664
                                ec.Report.Error (212, loc, "You can only take the address of unfixed expression inside of a fixed statement initializer");
 
665
                        }
 
666
 
 
667
                        type = PointerContainer.MakeType (ec.Module, Expr.Type);
 
668
                        eclass = ExprClass.Value;
 
669
                        return this;
 
670
                }
 
671
 
 
672
                Expression ResolvePrimitivePredefinedType (ResolveContext rc, Expression expr, TypeSpec[] predefined)
 
673
                {
 
674
                        expr = DoNumericPromotion (rc, Oper, expr);
 
675
                        TypeSpec expr_type = expr.Type;
 
676
                        foreach (TypeSpec t in predefined) {
 
677
                                if (t == expr_type)
 
678
                                        return expr;
 
679
                        }
 
680
                        return null;
 
681
                }
 
682
 
 
683
                //
 
684
                // Perform user-operator overload resolution
 
685
                //
 
686
                protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression expr)
 
687
                {
 
688
                        CSharp.Operator.OpType op_type;
 
689
                        switch (Oper) {
 
690
                        case Operator.LogicalNot:
 
691
                                op_type = CSharp.Operator.OpType.LogicalNot; break;
 
692
                        case Operator.OnesComplement:
 
693
                                op_type = CSharp.Operator.OpType.OnesComplement; break;
 
694
                        case Operator.UnaryNegation:
 
695
                                op_type = CSharp.Operator.OpType.UnaryNegation; break;
 
696
                        case Operator.UnaryPlus:
 
697
                                op_type = CSharp.Operator.OpType.UnaryPlus; break;
 
698
                        default:
 
699
                                throw new InternalErrorException (Oper.ToString ());
 
700
                        }
 
701
 
 
702
                        var methods = MemberCache.GetUserOperator (expr.Type, op_type, false);
 
703
                        if (methods == null)
 
704
                                return null;
 
705
 
 
706
                        Arguments args = new Arguments (1);
 
707
                        args.Add (new Argument (expr));
 
708
 
 
709
                        var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
 
710
                        var oper = res.ResolveOperator (ec, ref args);
 
711
 
 
712
                        if (oper == null)
 
713
                                return null;
 
714
 
 
715
                        Expr = args [0].Expr;
 
716
                        return new UserOperatorCall (oper, args, CreateExpressionTree, expr.Location);
 
717
                }
 
718
 
 
719
                //
 
720
                // Unary user type overload resolution
 
721
                //
 
722
                Expression ResolveUserType (ResolveContext ec, Expression expr, TypeSpec[] predefined)
 
723
                {
 
724
                        Expression best_expr = ResolveUserOperator (ec, expr);
 
725
                        if (best_expr != null)
 
726
                                return best_expr;
 
727
 
 
728
                        foreach (TypeSpec t in predefined) {
 
729
                                Expression oper_expr = Convert.ImplicitUserConversion (ec, expr, t, expr.Location);
 
730
                                if (oper_expr == null)
 
731
                                        continue;
 
732
 
 
733
                                if (oper_expr == ErrorExpression.Instance)
 
734
                                        return oper_expr;
 
735
 
 
736
                                //
 
737
                                // decimal type is predefined but has user-operators
 
738
                                //
 
739
                                if (oper_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal)
 
740
                                        oper_expr = ResolveUserType (ec, oper_expr, predefined);
 
741
                                else
 
742
                                        oper_expr = ResolvePrimitivePredefinedType (ec, oper_expr, predefined);
 
743
 
 
744
                                if (oper_expr == null)
 
745
                                        continue;
 
746
 
 
747
                                if (best_expr == null) {
 
748
                                        best_expr = oper_expr;
 
749
                                        continue;
 
750
                                }
 
751
 
 
752
                                int result = OverloadResolver.BetterTypeConversion (ec, best_expr.Type, t);
 
753
                                if (result == 0) {
 
754
                                        if ((oper_expr is UserOperatorCall || oper_expr is UserCast) && (best_expr is UserOperatorCall || best_expr is UserCast)) {
 
755
                                                ec.Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'",
 
756
                                                        OperName (Oper), expr.Type.GetSignatureForError ());
 
757
                                        } else {
 
758
                                                Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), expr.Type);
 
759
                                        }
 
760
 
 
761
                                        break;
 
762
                                }
 
763
 
 
764
                                if (result == 2)
 
765
                                        best_expr = oper_expr;
 
766
                        }
 
767
                        
 
768
                        if (best_expr == null)
 
769
                                return null;
 
770
                        
 
771
                        //
 
772
                        // HACK: Decimal user-operator is included in standard operators
 
773
                        //
 
774
                        if (best_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal)
 
775
                                return best_expr;
 
776
 
 
777
                        Expr = best_expr;
 
778
                        type = best_expr.Type;
 
779
                        return this;                    
 
780
                }
 
781
 
 
782
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
783
                {
 
784
                        Unary target = (Unary) t;
 
785
 
 
786
                        target.Expr = Expr.Clone (clonectx);
 
787
                }
 
788
                
 
789
                public override object Accept (StructuralVisitor visitor)
 
790
                {
 
791
                        return visitor.Visit (this);
 
792
                }
 
793
 
 
794
        }
 
795
 
 
796
        //
 
797
        // Unary operators are turned into Indirection expressions
 
798
        // after semantic analysis (this is so we can take the address
 
799
        // of an indirection).
 
800
        //
 
801
        public class Indirection : Expression, IMemoryLocation, IAssignMethod, IFixedExpression {
 
802
                Expression expr;
 
803
                LocalTemporary temporary;
 
804
                bool prepared;
 
805
                
 
806
                public Expression Expr {
 
807
                        get {
 
808
                                return expr;
 
809
                        }
 
810
                }
 
811
                
 
812
                public Indirection (Expression expr, Location l)
 
813
                {
 
814
                        this.expr = expr;
 
815
                        loc = l;
 
816
                }
 
817
 
 
818
                public override Expression CreateExpressionTree (ResolveContext ec)
 
819
                {
 
820
                        Error_PointerInsideExpressionTree (ec);
 
821
                        return null;
 
822
                }
 
823
                
 
824
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
825
                {
 
826
                        Indirection target = (Indirection) t;
 
827
                        target.expr = expr.Clone (clonectx);
 
828
                }               
 
829
                
 
830
                public override void Emit (EmitContext ec)
 
831
                {
 
832
                        if (!prepared)
 
833
                                expr.Emit (ec);
 
834
                        
 
835
                        ec.EmitLoadFromPtr (Type);
 
836
                }
 
837
 
 
838
                public void Emit (EmitContext ec, bool leave_copy)
 
839
                {
 
840
                        Emit (ec);
 
841
                        if (leave_copy) {
 
842
                                ec.Emit (OpCodes.Dup);
 
843
                                temporary = new LocalTemporary (expr.Type);
 
844
                                temporary.Store (ec);
 
845
                        }
 
846
                }
 
847
                
 
848
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
 
849
                {
 
850
                        prepared = prepare_for_load;
 
851
                        
 
852
                        expr.Emit (ec);
 
853
 
 
854
                        if (prepare_for_load)
 
855
                                ec.Emit (OpCodes.Dup);
 
856
                        
 
857
                        source.Emit (ec);
 
858
                        if (leave_copy) {
 
859
                                ec.Emit (OpCodes.Dup);
 
860
                                temporary = new LocalTemporary (source.Type);
 
861
                                temporary.Store (ec);
 
862
                        }
 
863
                        
 
864
                        ec.EmitStoreFromPtr (type);
 
865
                        
 
866
                        if (temporary != null) {
 
867
                                temporary.Emit (ec);
 
868
                                temporary.Release (ec);
 
869
                        }
 
870
                }
 
871
                
 
872
                public void AddressOf (EmitContext ec, AddressOp Mode)
 
873
                {
 
874
                        expr.Emit (ec);
 
875
                }
 
876
 
 
877
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
878
                {
 
879
                        return DoResolve (ec);
 
880
                }
 
881
 
 
882
                protected override Expression DoResolve (ResolveContext ec)
 
883
                {
 
884
                        expr = expr.Resolve (ec);
 
885
                        if (expr == null)
 
886
                                return null;
 
887
 
 
888
                        if (!ec.IsUnsafe)
 
889
                                UnsafeError (ec, loc);
 
890
 
 
891
                        var pc = expr.Type as PointerContainer;
 
892
 
 
893
                        if (pc == null) {
 
894
                                ec.Report.Error (193, loc, "The * or -> operator must be applied to a pointer");
 
895
                                return null;
 
896
                        }
 
897
 
 
898
                        type = pc.Element;
 
899
 
 
900
                        if (type.Kind == MemberKind.Void) {
 
901
                                Error_VoidPointerOperation (ec);
 
902
                                return null;
 
903
                        }
 
904
 
 
905
                        eclass = ExprClass.Variable;
 
906
                        return this;
 
907
                }
 
908
 
 
909
                public bool IsFixed {
 
910
                        get { return true; }
 
911
                }
 
912
 
 
913
                public override string ToString ()
 
914
                {
 
915
                        return "*(" + expr + ")";
 
916
                }
 
917
                
 
918
                public override object Accept (StructuralVisitor visitor)
 
919
                {
 
920
                        return visitor.Visit (this);
 
921
                }
 
922
        }
 
923
        
 
924
        /// <summary>
 
925
        ///   Unary Mutator expressions (pre and post ++ and --)
 
926
        /// </summary>
 
927
        ///
 
928
        /// <remarks>
 
929
        ///   UnaryMutator implements ++ and -- expressions.   It derives from
 
930
        ///   ExpressionStatement becuase the pre/post increment/decrement
 
931
        ///   operators can be used in a statement context.
 
932
        ///
 
933
        /// FIXME: Idea, we could split this up in two classes, one simpler
 
934
        /// for the common case, and one with the extra fields for more complex
 
935
        /// classes (indexers require temporary access;  overloaded require method)
 
936
        ///
 
937
        /// </remarks>
 
938
        public class UnaryMutator : ExpressionStatement
 
939
        {
 
940
                class DynamicPostMutator : Expression, IAssignMethod
 
941
                {
 
942
                        LocalTemporary temp;
 
943
                        Expression expr;
 
944
 
 
945
                        public DynamicPostMutator (Expression expr)
 
946
                        {
 
947
                                this.expr = expr;
 
948
                                this.type = expr.Type;
 
949
                                this.loc = expr.Location;
 
950
                        }
 
951
 
 
952
                        public override Expression CreateExpressionTree (ResolveContext ec)
 
953
                        {
 
954
                                throw new NotImplementedException ("ET");
 
955
                        }
 
956
 
 
957
                        protected override Expression DoResolve (ResolveContext rc)
 
958
                        {
 
959
                                eclass = expr.eclass;
 
960
                                return this;
 
961
                        }
 
962
 
 
963
                        public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
964
                        {
 
965
                                expr.DoResolveLValue (ec, right_side);
 
966
                                return DoResolve (ec);
 
967
                        }
 
968
 
 
969
                        public override void Emit (EmitContext ec)
 
970
                        {
 
971
                                temp.Emit (ec);
 
972
                        }
 
973
 
 
974
                        public void Emit (EmitContext ec, bool leave_copy)
 
975
                        {
 
976
                                throw new NotImplementedException ();
 
977
                        }
 
978
 
 
979
                        //
 
980
                        // Emits target assignment using unmodified source value
 
981
                        //
 
982
                        public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
 
983
                        {
 
984
                                //
 
985
                                // Allocate temporary variable to keep original value before it's modified
 
986
                                //
 
987
                                temp = new LocalTemporary (type);
 
988
                                expr.Emit (ec);
 
989
                                temp.Store (ec);
 
990
 
 
991
                                ((IAssignMethod) expr).EmitAssign (ec, source, false, prepare_for_load);
 
992
 
 
993
                                if (leave_copy)
 
994
                                        Emit (ec);
 
995
 
 
996
                                temp.Release (ec);
 
997
                                temp = null;
 
998
                        }
 
999
                }
 
1000
 
 
1001
                [Flags]
 
1002
                public enum Mode : byte {
 
1003
                        IsIncrement    = 0,
 
1004
                        IsDecrement    = 1,
 
1005
                        IsPre          = 0,
 
1006
                        IsPost         = 2,
 
1007
                        
 
1008
                        PreIncrement   = 0,
 
1009
                        PreDecrement   = IsDecrement,
 
1010
                        PostIncrement  = IsPost,
 
1011
                        PostDecrement  = IsPost | IsDecrement
 
1012
                }
 
1013
 
 
1014
                Mode mode;
 
1015
                bool is_expr, recurse;
 
1016
 
 
1017
                Expression expr;
 
1018
 
 
1019
                // Holds the real operation
 
1020
                Expression operation;
 
1021
                
 
1022
                public Mode UnaryMutatorMode {
 
1023
                        get {
 
1024
                                return mode;
 
1025
                        }
 
1026
                }
 
1027
                
 
1028
                public Expression Expr {
 
1029
                        get {
 
1030
                                return expr;
 
1031
                        }
 
1032
                }
 
1033
 
 
1034
                public UnaryMutator (Mode m, Expression e, Location loc)
 
1035
                {
 
1036
                        mode = m;
 
1037
                        this.loc = loc;
 
1038
                        expr = e;
 
1039
                }
 
1040
 
 
1041
                public override Expression CreateExpressionTree (ResolveContext ec)
 
1042
                {
 
1043
                        return new SimpleAssign (this, this).CreateExpressionTree (ec);
 
1044
                }
 
1045
 
 
1046
                public static TypeSpec[] CreatePredefinedOperatorsTable (BuiltinTypes types)
 
1047
                {
 
1048
                        //
 
1049
                        // Predefined ++ and -- operators exist for the following types: 
 
1050
                        // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal
 
1051
                        //
 
1052
                        return new TypeSpec[] {
 
1053
                                types.Int,
 
1054
                                types.Long,
 
1055
 
 
1056
                                types.SByte,
 
1057
                                types.Byte,
 
1058
                                types.Short,
 
1059
                                types.UInt,
 
1060
                                types.ULong,
 
1061
                                types.Char,
 
1062
                                types.Float,
 
1063
                                types.Double,
 
1064
                                types.Decimal
 
1065
                        };
 
1066
                }
 
1067
 
 
1068
                protected override Expression DoResolve (ResolveContext ec)
 
1069
                {
 
1070
                        expr = expr.Resolve (ec);
 
1071
                        
 
1072
                        if (expr == null)
 
1073
                                return null;
 
1074
 
 
1075
                        if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
1076
                                //
 
1077
                                // Handle postfix unary operators using local
 
1078
                                // temporary variable
 
1079
                                //
 
1080
                                if ((mode & Mode.IsPost) != 0)
 
1081
                                        expr = new DynamicPostMutator (expr);
 
1082
 
 
1083
                                Arguments args = new Arguments (1);
 
1084
                                args.Add (new Argument (expr));
 
1085
                                return new SimpleAssign (expr, new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc)).Resolve (ec);
 
1086
                        }
 
1087
 
 
1088
                        if (expr.Type.IsNullableType)
 
1089
                                return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec);
 
1090
 
 
1091
                        eclass = ExprClass.Value;
 
1092
                        type = expr.Type;
 
1093
 
 
1094
                        if (expr is RuntimeValueExpression) {
 
1095
                                operation = expr;
 
1096
                        } else {
 
1097
                                // Use itself at the top of the stack
 
1098
                                operation = new EmptyExpression (type);
 
1099
                        }
 
1100
 
 
1101
                        //
 
1102
                        // The operand of the prefix/postfix increment decrement operators
 
1103
                        // should be an expression that is classified as a variable,
 
1104
                        // a property access or an indexer access
 
1105
                        //
 
1106
                        // TODO: Move to parser, expr is ATypeNameExpression
 
1107
                        if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) {
 
1108
                                expr = expr.ResolveLValue (ec, expr);
 
1109
                        } else {
 
1110
                                ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer");
 
1111
                        }
 
1112
 
 
1113
                        //
 
1114
                        // Step 1: Try to find a user operator, it has priority over predefined ones
 
1115
                        //
 
1116
                        var user_op = IsDecrement ? Operator.OpType.Decrement : Operator.OpType.Increment;
 
1117
                        var methods = MemberCache.GetUserOperator (type, user_op, false);
 
1118
 
 
1119
                        if (methods != null) {
 
1120
                                Arguments args = new Arguments (1);
 
1121
                                args.Add (new Argument (expr));
 
1122
 
 
1123
                                var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc);
 
1124
                                var method = res.ResolveOperator (ec, ref args);
 
1125
                                if (method == null)
 
1126
                                        return null;
 
1127
 
 
1128
                                args[0].Expr = operation;
 
1129
                                operation = new UserOperatorCall (method, args, null, loc);
 
1130
                                operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
 
1131
                                return this;
 
1132
                        }
 
1133
 
 
1134
                        //
 
1135
                        // Step 2: Try predefined types
 
1136
                        //
 
1137
 
 
1138
                        Expression source = null;
 
1139
                        bool primitive_type;
 
1140
 
 
1141
                        //
 
1142
                        // Predefined without user conversion first for speed-up
 
1143
                        //
 
1144
                        // Predefined ++ and -- operators exist for the following types: 
 
1145
                        // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal
 
1146
                        //
 
1147
                        switch (type.BuiltinType) {
 
1148
                        case BuiltinTypeSpec.Type.Byte:
 
1149
                        case BuiltinTypeSpec.Type.SByte:
 
1150
                        case BuiltinTypeSpec.Type.Short:
 
1151
                        case BuiltinTypeSpec.Type.UShort:
 
1152
                        case BuiltinTypeSpec.Type.Int:
 
1153
                        case BuiltinTypeSpec.Type.UInt:
 
1154
                        case BuiltinTypeSpec.Type.Long:
 
1155
                        case BuiltinTypeSpec.Type.ULong:
 
1156
                        case BuiltinTypeSpec.Type.Char:
 
1157
                        case BuiltinTypeSpec.Type.Float:
 
1158
                        case BuiltinTypeSpec.Type.Double:
 
1159
                        case BuiltinTypeSpec.Type.Decimal:
 
1160
                                source = operation;
 
1161
                                primitive_type = true;
 
1162
                                break;
 
1163
                        default:
 
1164
                                primitive_type = false;
 
1165
 
 
1166
                                // ++/-- on pointer variables of all types except void*
 
1167
                                if (type.IsPointer) {
 
1168
                                        if (((PointerContainer) type).Element.Kind == MemberKind.Void) {
 
1169
                                                Error_VoidPointerOperation (ec);
 
1170
                                                return null;
 
1171
                                        }
 
1172
 
 
1173
                                        source = operation;
 
1174
                                } else {
 
1175
                                        foreach (var t in ec.BuiltinTypes.OperatorsUnaryMutator) {
 
1176
                                                source = Convert.ImplicitUserConversion (ec, operation, t, loc);
 
1177
 
 
1178
                                                // LAMESPEC: It should error on ambiguous operators but that would make us incompatible
 
1179
                                                if (source != null) {
 
1180
                                                        break;
 
1181
                                                }
 
1182
                                        }
 
1183
                                }
 
1184
 
 
1185
                                // ++/-- on enum types
 
1186
                                if (source == null && type.IsEnum)
 
1187
                                        source = operation;
 
1188
 
 
1189
                                if (source == null) {
 
1190
                                        Unary.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type);
 
1191
                                        return null;
 
1192
                                }
 
1193
 
 
1194
                                break;
 
1195
                        }
 
1196
 
 
1197
                        var one = new IntConstant (ec.BuiltinTypes, 1, loc);
 
1198
                        var op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition;
 
1199
                        operation = new Binary (op, source, one, loc);
 
1200
                        operation = operation.Resolve (ec);
 
1201
                        if (operation == null)
 
1202
                                throw new NotImplementedException ("should not be reached");
 
1203
 
 
1204
                        if (operation.Type != type) {
 
1205
                                if (primitive_type)
 
1206
                                        operation = Convert.ExplicitNumericConversion (ec, operation, type);
 
1207
                                else
 
1208
                                        operation = Convert.ImplicitConversionRequired (ec, operation, type, loc);
 
1209
                        }
 
1210
 
 
1211
                        return this;
 
1212
                }
 
1213
 
 
1214
                void EmitCode (EmitContext ec, bool is_expr)
 
1215
                {
 
1216
                        recurse = true;
 
1217
                        this.is_expr = is_expr;
 
1218
                        ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true);
 
1219
                }
 
1220
 
 
1221
                public override void Emit (EmitContext ec)
 
1222
                {
 
1223
                        //
 
1224
                        // We use recurse to allow ourselfs to be the source
 
1225
                        // of an assignment. This little hack prevents us from
 
1226
                        // having to allocate another expression
 
1227
                        //
 
1228
                        if (recurse) {
 
1229
                                ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement));
 
1230
 
 
1231
                                operation.Emit (ec);
 
1232
 
 
1233
                                recurse = false;
 
1234
                                return;
 
1235
                        }
 
1236
 
 
1237
                        EmitCode (ec, true);
 
1238
                }
 
1239
 
 
1240
                public override void EmitStatement (EmitContext ec)
 
1241
                {
 
1242
                        EmitCode (ec, false);
 
1243
                }
 
1244
 
 
1245
                //
 
1246
                // Converts operator to System.Linq.Expressions.ExpressionType enum name
 
1247
                //
 
1248
                string GetOperatorExpressionTypeName ()
 
1249
                {
 
1250
                        return IsDecrement ? "Decrement" : "Increment";
 
1251
                }
 
1252
 
 
1253
                bool IsDecrement {
 
1254
                        get { return (mode & Mode.IsDecrement) != 0; }
 
1255
                }
 
1256
 
 
1257
 
 
1258
#if NET_4_0
 
1259
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
1260
                {
 
1261
                        var target = ((RuntimeValueExpression) expr).MetaObject.Expression;
 
1262
                        var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type);
 
1263
                        return SLE.Expression.Assign (target, source);
 
1264
                }
 
1265
#endif
 
1266
 
 
1267
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
1268
                {
 
1269
                        UnaryMutator target = (UnaryMutator) t;
 
1270
 
 
1271
                        target.expr = expr.Clone (clonectx);
 
1272
                }
 
1273
                public override object Accept (StructuralVisitor visitor)
 
1274
                {
 
1275
                        return visitor.Visit (this);
 
1276
                }
 
1277
 
 
1278
        }
 
1279
 
 
1280
        /// <summary>
 
1281
        ///   Base class for the `Is' and `As' classes. 
 
1282
        /// </summary>
 
1283
        ///
 
1284
        /// <remarks>
 
1285
        ///   FIXME: Split this in two, and we get to save the `Operator' Oper
 
1286
        ///   size. 
 
1287
        /// </remarks>
 
1288
        public abstract class Probe : Expression {
 
1289
                public Expression ProbeType;
 
1290
                protected Expression expr;
 
1291
                protected TypeSpec probe_type_expr;
 
1292
                
 
1293
                public Probe (Expression expr, Expression probe_type, Location l)
 
1294
                {
 
1295
                        ProbeType = probe_type;
 
1296
                        loc = l;
 
1297
                        this.expr = expr;
 
1298
                }
 
1299
 
 
1300
                public Expression Expr {
 
1301
                        get {
 
1302
                                return expr;
 
1303
                        }
 
1304
                }
 
1305
 
 
1306
                protected override Expression DoResolve (ResolveContext ec)
 
1307
                {
 
1308
                        probe_type_expr = ProbeType.ResolveAsType (ec);
 
1309
                        if (probe_type_expr == null)
 
1310
                                return null;
 
1311
 
 
1312
                        expr = expr.Resolve (ec);
 
1313
                        if (expr == null)
 
1314
                                return null;
 
1315
 
 
1316
                        if (probe_type_expr.IsStatic) {
 
1317
                                ec.Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type",
 
1318
                                        OperatorName);
 
1319
                        }
 
1320
                        
 
1321
                        if (expr.Type.IsPointer || probe_type_expr.IsPointer) {
 
1322
                                ec.Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type",
 
1323
                                        OperatorName);
 
1324
                                return null;
 
1325
                        }
 
1326
 
 
1327
                        if (expr.Type == InternalType.AnonymousMethod) {
 
1328
                                ec.Report.Error (837, loc, "The `{0}' operator cannot be applied to a lambda expression or anonymous method",
 
1329
                                        OperatorName);
 
1330
                                return null;
 
1331
                        }
 
1332
 
 
1333
                        return this;
 
1334
                }
 
1335
 
 
1336
                protected abstract string OperatorName { get; }
 
1337
 
 
1338
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
1339
                {
 
1340
                        Probe target = (Probe) t;
 
1341
 
 
1342
                        target.expr = expr.Clone (clonectx);
 
1343
                        target.ProbeType = ProbeType.Clone (clonectx);
 
1344
                }
 
1345
 
 
1346
        }
 
1347
 
 
1348
        /// <summary>
 
1349
        ///   Implementation of the `is' operator.
 
1350
        /// </summary>
 
1351
        public class Is : Probe {
 
1352
                Nullable.Unwrap expr_unwrap;
 
1353
 
 
1354
                public Is (Expression expr, Expression probe_type, Location l)
 
1355
                        : base (expr, probe_type, l)
 
1356
                {
 
1357
                }
 
1358
 
 
1359
                public override Expression CreateExpressionTree (ResolveContext ec)
 
1360
                {
 
1361
                        Arguments args = Arguments.CreateForExpressionTree (ec, null,
 
1362
                                expr.CreateExpressionTree (ec),
 
1363
                                new TypeOf (probe_type_expr, loc));
 
1364
 
 
1365
                        return CreateExpressionFactoryCall (ec, "TypeIs", args);
 
1366
                }
 
1367
                
 
1368
                public override void Emit (EmitContext ec)
 
1369
                {
 
1370
                        if (expr_unwrap != null) {
 
1371
                                expr_unwrap.EmitCheck (ec);
 
1372
                                return;
 
1373
                        }
 
1374
 
 
1375
                        expr.Emit (ec);
 
1376
 
 
1377
                        // Only to make verifier happy
 
1378
                        if (probe_type_expr.IsGenericParameter && TypeSpec.IsValueType (expr.Type))
 
1379
                                ec.Emit (OpCodes.Box, expr.Type);
 
1380
 
 
1381
                        ec.Emit (OpCodes.Isinst, probe_type_expr);
 
1382
                        ec.Emit (OpCodes.Ldnull);
 
1383
                        ec.Emit (OpCodes.Cgt_Un);
 
1384
                }
 
1385
 
 
1386
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 
1387
                {
 
1388
                        if (expr_unwrap != null) {
 
1389
                                expr_unwrap.EmitCheck (ec);
 
1390
                        } else {
 
1391
                                expr.Emit (ec);
 
1392
                                ec.Emit (OpCodes.Isinst, probe_type_expr);
 
1393
                        }                       
 
1394
                        ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
 
1395
                }
 
1396
                
 
1397
                Expression CreateConstantResult (ResolveContext ec, bool result)
 
1398
                {
 
1399
                        if (result)
 
1400
                                ec.Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type",
 
1401
                                        TypeManager.CSharpName (probe_type_expr));
 
1402
                        else
 
1403
                                ec.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type",
 
1404
                                        TypeManager.CSharpName (probe_type_expr));
 
1405
 
 
1406
                        return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, result, loc), this);
 
1407
                }
 
1408
 
 
1409
                protected override Expression DoResolve (ResolveContext ec)
 
1410
                {
 
1411
                        if (base.DoResolve (ec) == null)
 
1412
                                return null;
 
1413
 
 
1414
                        TypeSpec d = expr.Type;
 
1415
                        bool d_is_nullable = false;
 
1416
 
 
1417
                        //
 
1418
                        // If E is a method group or the null literal, or if the type of E is a reference
 
1419
                        // type or a nullable type and the value of E is null, the result is false
 
1420
                        //
 
1421
                        if (expr.IsNull || expr.eclass == ExprClass.MethodGroup)
 
1422
                                return CreateConstantResult (ec, false);
 
1423
 
 
1424
                        if (d.IsNullableType) {
 
1425
                                var ut = Nullable.NullableInfo.GetUnderlyingType (d);
 
1426
                                if (!ut.IsGenericParameter) {
 
1427
                                        d = ut;
 
1428
                                        d_is_nullable = true;
 
1429
                                }
 
1430
                        }
 
1431
 
 
1432
                        type = ec.BuiltinTypes.Bool;
 
1433
                        eclass = ExprClass.Value;
 
1434
                        TypeSpec t = probe_type_expr;
 
1435
                        bool t_is_nullable = false;
 
1436
                        if (t.IsNullableType) {
 
1437
                                var ut = Nullable.NullableInfo.GetUnderlyingType (t);
 
1438
                                if (!ut.IsGenericParameter) {
 
1439
                                        t = ut;
 
1440
                                        t_is_nullable = true;
 
1441
                                }
 
1442
                        }
 
1443
 
 
1444
                        if (t.IsStruct) {
 
1445
                                if (d == t) {
 
1446
                                        //
 
1447
                                        // D and T are the same value types but D can be null
 
1448
                                        //
 
1449
                                        if (d_is_nullable && !t_is_nullable) {
 
1450
                                                expr_unwrap = Nullable.Unwrap.Create (expr, false);
 
1451
                                                return this;
 
1452
                                        }
 
1453
                                        
 
1454
                                        //
 
1455
                                        // The result is true if D and T are the same value types
 
1456
                                        //
 
1457
                                        return CreateConstantResult (ec, true);
 
1458
                                }
 
1459
 
 
1460
                                var tp = d as TypeParameterSpec;
 
1461
                                if (tp != null)
 
1462
                                        return ResolveGenericParameter (ec, t, tp);
 
1463
 
 
1464
                                //
 
1465
                                // An unboxing conversion exists
 
1466
                                //
 
1467
                                if (Convert.ExplicitReferenceConversionExists (d, t))
 
1468
                                        return this;
 
1469
                        } else {
 
1470
                                if (TypeManager.IsGenericParameter (t))
 
1471
                                        return ResolveGenericParameter (ec, d, (TypeParameterSpec) t);
 
1472
 
 
1473
                                if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
1474
                                        ec.Report.Warning (1981, 3, loc,
 
1475
                                                "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'",
 
1476
                                                OperatorName, t.GetSignatureForError ());
 
1477
                                }
 
1478
 
 
1479
                                if (TypeManager.IsGenericParameter (d))
 
1480
                                        return ResolveGenericParameter (ec, t, (TypeParameterSpec) d);
 
1481
 
 
1482
                                if (TypeSpec.IsValueType (d)) {
 
1483
                                        if (Convert.ImplicitBoxingConversion (null, d, t) != null) {
 
1484
                                                if (d_is_nullable && !t_is_nullable) {
 
1485
                                                        expr_unwrap = Nullable.Unwrap.Create (expr, false);
 
1486
                                                        return this;
 
1487
                                                }
 
1488
 
 
1489
                                                return CreateConstantResult (ec, true);
 
1490
                                        }
 
1491
                                } else {
 
1492
                                //      if (InflatedTypeSpec.ContainsTypeParameter (d))
 
1493
                                //              return this;
 
1494
 
 
1495
                                        if (Convert.ImplicitReferenceConversionExists (d, t) ||
 
1496
                                                Convert.ExplicitReferenceConversionExists (d, t)) {
 
1497
                                                return this;
 
1498
                                        }
 
1499
                                }
 
1500
                        }
 
1501
 
 
1502
                        return CreateConstantResult (ec, false);
 
1503
                }
 
1504
 
 
1505
                Expression ResolveGenericParameter (ResolveContext ec, TypeSpec d, TypeParameterSpec t)
 
1506
                {
 
1507
                        if (t.IsReferenceType) {
 
1508
                                if (d.IsStruct)
 
1509
                                        return CreateConstantResult (ec, false);
 
1510
                        }
 
1511
 
 
1512
                        if (TypeManager.IsGenericParameter (expr.Type)) {
 
1513
                                if (expr.Type == d && TypeSpec.IsValueType (t))
 
1514
                                        return CreateConstantResult (ec, true);
 
1515
 
 
1516
                                expr = new BoxedCast (expr, d);
 
1517
                        }
 
1518
 
 
1519
                        return this;
 
1520
                }
 
1521
                
 
1522
                protected override string OperatorName {
 
1523
                        get { return "is"; }
 
1524
                }
 
1525
                
 
1526
                public override object Accept (StructuralVisitor visitor)
 
1527
                {
 
1528
                        return visitor.Visit (this);
 
1529
                }
 
1530
        }
 
1531
 
 
1532
        /// <summary>
 
1533
        ///   Implementation of the `as' operator.
 
1534
        /// </summary>
 
1535
        public class As : Probe {
 
1536
                Expression resolved_type;
 
1537
                
 
1538
                public As (Expression expr, Expression probe_type, Location l)
 
1539
                        : base (expr, probe_type, l)
 
1540
                {
 
1541
                }
 
1542
 
 
1543
                public override Expression CreateExpressionTree (ResolveContext ec)
 
1544
                {
 
1545
                        Arguments args = Arguments.CreateForExpressionTree (ec, null,
 
1546
                                expr.CreateExpressionTree (ec),
 
1547
                                new TypeOf (probe_type_expr, loc));
 
1548
 
 
1549
                        return CreateExpressionFactoryCall (ec, "TypeAs", args);
 
1550
                }
 
1551
 
 
1552
                public override void Emit (EmitContext ec)
 
1553
                {
 
1554
                        expr.Emit (ec);
 
1555
 
 
1556
                        ec.Emit (OpCodes.Isinst, type);
 
1557
 
 
1558
                        if (TypeManager.IsGenericParameter (type) || type.IsNullableType)
 
1559
                                ec.Emit (OpCodes.Unbox_Any, type);
 
1560
                }
 
1561
 
 
1562
                protected override Expression DoResolve (ResolveContext ec)
 
1563
                {
 
1564
                        if (resolved_type == null) {
 
1565
                                resolved_type = base.DoResolve (ec);
 
1566
 
 
1567
                                if (resolved_type == null)
 
1568
                                        return null;
 
1569
                        }
 
1570
 
 
1571
                        type = probe_type_expr;
 
1572
                        eclass = ExprClass.Value;
 
1573
                        TypeSpec etype = expr.Type;
 
1574
 
 
1575
                        if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) {
 
1576
                                if (TypeManager.IsGenericParameter (type)) {
 
1577
                                        ec.Report.Error (413, loc,
 
1578
                                                "The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint",
 
1579
                                                probe_type_expr.GetSignatureForError ());
 
1580
                                } else {
 
1581
                                        ec.Report.Error (77, loc,
 
1582
                                                "The `as' operator cannot be used with a non-nullable value type `{0}'",
 
1583
                                                TypeManager.CSharpName (type));
 
1584
                                }
 
1585
                                return null;
 
1586
                        }
 
1587
 
 
1588
                        if (expr.IsNull && type.IsNullableType) {
 
1589
                                return Nullable.LiftedNull.CreateFromExpression (ec, this);
 
1590
                        }
 
1591
 
 
1592
                        // If the compile-time type of E is dynamic, unlike the cast operator the as operator is not dynamically bound
 
1593
                        if (etype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
1594
                                return this;
 
1595
                        }
 
1596
                        
 
1597
                        Expression e = Convert.ImplicitConversionStandard (ec, expr, type, loc);
 
1598
                        if (e != null) {
 
1599
                                e = EmptyCast.Create (e, type);
 
1600
                                return ReducedExpression.Create (e, this).Resolve (ec);
 
1601
                        }
 
1602
 
 
1603
                        if (Convert.ExplicitReferenceConversionExists (etype, type)){
 
1604
                                if (TypeManager.IsGenericParameter (etype))
 
1605
                                        expr = new BoxedCast (expr, etype);
 
1606
 
 
1607
                                return this;
 
1608
                        }
 
1609
 
 
1610
                        if (InflatedTypeSpec.ContainsTypeParameter (etype) || InflatedTypeSpec.ContainsTypeParameter (type)) {
 
1611
                                expr = new BoxedCast (expr, etype);
 
1612
                                return this;
 
1613
                        }
 
1614
 
 
1615
                        ec.Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion",
 
1616
                                TypeManager.CSharpName (etype), TypeManager.CSharpName (type));
 
1617
 
 
1618
                        return null;
 
1619
                }
 
1620
 
 
1621
                protected override string OperatorName {
 
1622
                        get { return "as"; }
 
1623
                }
 
1624
                public override object Accept (StructuralVisitor visitor)
 
1625
                {
 
1626
                        return visitor.Visit (this);
 
1627
                }
 
1628
 
 
1629
        }
 
1630
        
 
1631
        //
 
1632
        // This represents a typecast in the source language.
 
1633
        //
 
1634
        public class Cast : ShimExpression {
 
1635
                Expression target_type;
 
1636
 
 
1637
                public Cast (Expression cast_type, Expression expr, Location loc)
 
1638
                        : base (expr)
 
1639
                {
 
1640
                        this.target_type = cast_type;
 
1641
                        this.loc = loc;
 
1642
                }
 
1643
 
 
1644
                public Expression TargetType {
 
1645
                        get { return target_type; }
 
1646
                }
 
1647
 
 
1648
                protected override Expression DoResolve (ResolveContext ec)
 
1649
                {
 
1650
                        expr = expr.Resolve (ec);
 
1651
                        if (expr == null)
 
1652
                                return null;
 
1653
 
 
1654
                        type = target_type.ResolveAsType (ec);
 
1655
                        if (type == null)
 
1656
                                return null;
 
1657
 
 
1658
                        if (type.IsStatic) {
 
1659
                                ec.Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type));
 
1660
                                return null;
 
1661
                        }
 
1662
 
 
1663
                        eclass = ExprClass.Value;
 
1664
 
 
1665
                        Constant c = expr as Constant;
 
1666
                        if (c != null) {
 
1667
                                c = c.TryReduce (ec, type, loc);
 
1668
                                if (c != null)
 
1669
                                        return c;
 
1670
                        }
 
1671
 
 
1672
                        if (type.IsPointer && !ec.IsUnsafe) {
 
1673
                                UnsafeError (ec, loc);
 
1674
                        }
 
1675
 
 
1676
                        var res = Convert.ExplicitConversion (ec, expr, type, loc);
 
1677
                        if (res == expr)
 
1678
                                return EmptyCast.Create (res, type);
 
1679
 
 
1680
                        return res;
 
1681
                }
 
1682
                
 
1683
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
1684
                {
 
1685
                        Cast target = (Cast) t;
 
1686
 
 
1687
                        target.target_type = target_type.Clone (clonectx);
 
1688
                        target.expr = expr.Clone (clonectx);
 
1689
                }
 
1690
 
 
1691
                public override object Accept (StructuralVisitor visitor)
 
1692
                {
 
1693
                        return visitor.Visit (this);
 
1694
                }
 
1695
        }
 
1696
 
 
1697
        public class ImplicitCast : ShimExpression
 
1698
        {
 
1699
                bool arrayAccess;
 
1700
 
 
1701
                public ImplicitCast (Expression expr, TypeSpec target, bool arrayAccess)
 
1702
                        : base (expr)
 
1703
                {
 
1704
                        this.loc = expr.Location;
 
1705
                        this.type = target;
 
1706
                        this.arrayAccess = arrayAccess;
 
1707
                }
 
1708
 
 
1709
                protected override Expression DoResolve (ResolveContext ec)
 
1710
                {
 
1711
                        expr = expr.Resolve (ec);
 
1712
                        if (expr == null)
 
1713
                                return null;
 
1714
 
 
1715
                        if (arrayAccess)
 
1716
                                expr = ConvertExpressionToArrayIndex (ec, expr);
 
1717
                        else
 
1718
                                expr = Convert.ImplicitConversionRequired (ec, expr, type, loc);
 
1719
 
 
1720
                        return expr;
 
1721
                }
 
1722
        }
 
1723
        
 
1724
        //
 
1725
        // C# 2.0 Default value expression
 
1726
        //
 
1727
        public class DefaultValueExpression : Expression
 
1728
        {
 
1729
                Expression expr;
 
1730
                
 
1731
                
 
1732
                public Expression Expr {
 
1733
                        get {
 
1734
                                return this.expr; 
 
1735
                        }
 
1736
                }
 
1737
 
 
1738
                public DefaultValueExpression (Expression expr, Location loc)
 
1739
                {
 
1740
                        this.expr = expr;
 
1741
                        this.loc = loc;
 
1742
                }
 
1743
 
 
1744
                public override Expression CreateExpressionTree (ResolveContext ec)
 
1745
                {
 
1746
                        Arguments args = new Arguments (2);
 
1747
                        args.Add (new Argument (this));
 
1748
                        args.Add (new Argument (new TypeOf (type, loc)));
 
1749
                        return CreateExpressionFactoryCall (ec, "Constant", args);
 
1750
                }
 
1751
 
 
1752
                protected override Expression DoResolve (ResolveContext ec)
 
1753
                {
 
1754
                        type = expr.ResolveAsType (ec);
 
1755
                        if (type == null)
 
1756
                                return null;
 
1757
 
 
1758
                        if (type.IsStatic) {
 
1759
                                ec.Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type");
 
1760
                        }
 
1761
 
 
1762
                        if (type.IsPointer)
 
1763
                                return new NullLiteral (Location).ConvertImplicitly (type);
 
1764
 
 
1765
                        if (TypeSpec.IsReferenceType (type))
 
1766
                                return new NullConstant (type, loc);
 
1767
 
 
1768
                        Constant c = New.Constantify (type, expr.Location);
 
1769
                        if (c != null)
 
1770
                                return c;
 
1771
 
 
1772
                        eclass = ExprClass.Variable;
 
1773
                        return this;
 
1774
                }
 
1775
 
 
1776
                public override void Emit (EmitContext ec)
 
1777
                {
 
1778
                        LocalTemporary temp_storage = new LocalTemporary(type);
 
1779
 
 
1780
                        temp_storage.AddressOf(ec, AddressOp.LoadStore);
 
1781
                        ec.Emit(OpCodes.Initobj, type);
 
1782
                        temp_storage.Emit(ec);
 
1783
                }
 
1784
 
 
1785
#if NET_4_0 && !STATIC
 
1786
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
1787
                {
 
1788
                        return SLE.Expression.Default (type.GetMetaInfo ());
 
1789
                }
 
1790
#endif
 
1791
 
 
1792
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
1793
                {
 
1794
                        DefaultValueExpression target = (DefaultValueExpression) t;
 
1795
                        
 
1796
                        target.expr = expr.Clone (clonectx);
 
1797
                }
 
1798
                
 
1799
                public override object Accept (StructuralVisitor visitor)
 
1800
                {
 
1801
                        return visitor.Visit (this);
 
1802
                }
 
1803
        }
 
1804
 
 
1805
        /// <summary>
 
1806
        ///   Binary operators
 
1807
        /// </summary>
 
1808
        public class Binary : Expression, IDynamicBinder
 
1809
        {
 
1810
                public class PredefinedOperator
 
1811
                {
 
1812
                        protected readonly TypeSpec left;
 
1813
                        protected readonly TypeSpec right;
 
1814
                        public readonly Operator OperatorsMask;
 
1815
                        public TypeSpec ReturnType;
 
1816
 
 
1817
                        public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
 
1818
                                : this (ltype, rtype, op_mask, ltype)
 
1819
                        {
 
1820
                        }
 
1821
 
 
1822
                        public PredefinedOperator (TypeSpec type, Operator op_mask, TypeSpec return_type)
 
1823
                                : this (type, type, op_mask, return_type)
 
1824
                        {
 
1825
                        }
 
1826
 
 
1827
                        public PredefinedOperator (TypeSpec type, Operator op_mask)
 
1828
                                : this (type, type, op_mask, type)
 
1829
                        {
 
1830
                        }
 
1831
 
 
1832
                        public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type)
 
1833
                        {
 
1834
                                if ((op_mask & Operator.ValuesOnlyMask) != 0)
 
1835
                                        throw new InternalErrorException ("Only masked values can be used");
 
1836
 
 
1837
                                this.left = ltype;
 
1838
                                this.right = rtype;
 
1839
                                this.OperatorsMask = op_mask;
 
1840
                                this.ReturnType = return_type;
 
1841
                        }
 
1842
 
 
1843
                        public virtual Expression ConvertResult (ResolveContext ec, Binary b)
 
1844
                        {
 
1845
                                b.type = ReturnType;
 
1846
 
 
1847
                                b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
 
1848
                                b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
 
1849
 
 
1850
                                //
 
1851
                                // A user operators does not support multiple user conversions, but decimal type
 
1852
                                // is considered to be predefined type therefore we apply predefined operators rules
 
1853
                                // and then look for decimal user-operator implementation
 
1854
                                //
 
1855
                                if (left.BuiltinType == BuiltinTypeSpec.Type.Decimal)
 
1856
                                        return b.ResolveUserOperator (ec, b.left, b.right);
 
1857
 
 
1858
                                var c = b.right as Constant;
 
1859
                                if (c != null) {
 
1860
                                        if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.Subtraction || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator))))
 
1861
                                                return ReducedExpression.Create (b.left, b).Resolve (ec);
 
1862
                                        if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger)
 
1863
                                                return ReducedExpression.Create (b.left, b).Resolve (ec);
 
1864
                                        return b;
 
1865
                                }
 
1866
 
 
1867
                                c = b.left as Constant;
 
1868
                                if (c != null) {
 
1869
                                        if (c.IsDefaultValue && (b.oper == Operator.Addition || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator))))
 
1870
                                                return ReducedExpression.Create (b.right, b).Resolve (ec);
 
1871
                                        if (b.oper == Operator.Multiply && c.IsOneInteger)
 
1872
                                                return ReducedExpression.Create (b.right, b).Resolve (ec);
 
1873
                                        return b;
 
1874
                                }
 
1875
 
 
1876
                                return b;
 
1877
                        }
 
1878
 
 
1879
                        public bool IsPrimitiveApplicable (TypeSpec ltype, TypeSpec rtype)
 
1880
                        {
 
1881
                                //
 
1882
                                // We are dealing with primitive types only
 
1883
                                //
 
1884
                                return left == ltype && ltype == rtype;
 
1885
                        }
 
1886
 
 
1887
                        public virtual bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr)
 
1888
                        {
 
1889
                                // Quick path
 
1890
                                if (left == lexpr.Type && right == rexpr.Type)
 
1891
                                        return true;
 
1892
 
 
1893
                                return Convert.ImplicitConversionExists (ec, lexpr, left) &&
 
1894
                                        Convert.ImplicitConversionExists (ec, rexpr, right);
 
1895
                        }
 
1896
 
 
1897
                        public PredefinedOperator ResolveBetterOperator (ResolveContext ec, PredefinedOperator best_operator)
 
1898
                        {
 
1899
                                int result = 0;
 
1900
                                if (left != null && best_operator.left != null) {
 
1901
                                        result = OverloadResolver.BetterTypeConversion (ec, best_operator.left, left);
 
1902
                                }
 
1903
 
 
1904
                                //
 
1905
                                // When second argument is same as the first one, the result is same
 
1906
                                //
 
1907
                                if (right != null && (left != right || best_operator.left != best_operator.right)) {
 
1908
                                        result |= OverloadResolver.BetterTypeConversion (ec, best_operator.right, right);
 
1909
                                }
 
1910
 
 
1911
                                if (result == 0 || result > 2)
 
1912
                                        return null;
 
1913
 
 
1914
                                return result == 1 ? best_operator : this;
 
1915
                        }
 
1916
                }
 
1917
 
 
1918
                sealed class PredefinedStringOperator : PredefinedOperator
 
1919
                {
 
1920
                        public PredefinedStringOperator (TypeSpec type, Operator op_mask, TypeSpec retType)
 
1921
                                : base (type, type, op_mask, retType)
 
1922
                        {
 
1923
                        }
 
1924
 
 
1925
                        public PredefinedStringOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)
 
1926
                                : base (ltype, rtype, op_mask, retType)
 
1927
                        {
 
1928
                        }
 
1929
 
 
1930
                        public override Expression ConvertResult (ResolveContext ec, Binary b)
 
1931
                        {
 
1932
                                //
 
1933
                                // Use original expression for nullable arguments
 
1934
                                //
 
1935
                                Nullable.Unwrap unwrap = b.left as Nullable.Unwrap;
 
1936
                                if (unwrap != null)
 
1937
                                        b.left = unwrap.Original;
 
1938
 
 
1939
                                unwrap = b.right as Nullable.Unwrap;
 
1940
                                if (unwrap != null)
 
1941
                                        b.right = unwrap.Original;
 
1942
 
 
1943
                                b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
 
1944
                                b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
 
1945
 
 
1946
                                //
 
1947
                                // Start a new concat expression using converted expression
 
1948
                                //
 
1949
                                return StringConcat.Create (ec, b.left, b.right, b.loc);
 
1950
                        }
 
1951
                }
 
1952
 
 
1953
                sealed class PredefinedShiftOperator : PredefinedOperator
 
1954
                {
 
1955
                        public PredefinedShiftOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
 
1956
                                : base (ltype, rtype, op_mask)
 
1957
                        {
 
1958
                        }
 
1959
 
 
1960
                        public override Expression ConvertResult (ResolveContext ec, Binary b)
 
1961
                        {
 
1962
                                b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
 
1963
 
 
1964
                                Expression expr_tree_expr = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
 
1965
 
 
1966
                                int right_mask = left.BuiltinType == BuiltinTypeSpec.Type.Int || left.BuiltinType == BuiltinTypeSpec.Type.UInt ? 0x1f : 0x3f;
 
1967
 
 
1968
                                //
 
1969
                                // b = b.left >> b.right & (0x1f|0x3f)
 
1970
                                //
 
1971
                                b.right = new Binary (Operator.BitwiseAnd,
 
1972
                                        b.right, new IntConstant (ec.BuiltinTypes, right_mask, b.right.Location), b.loc).Resolve (ec);
 
1973
 
 
1974
                                //
 
1975
                                // Expression tree representation does not use & mask
 
1976
                                //
 
1977
                                b.right = ReducedExpression.Create (b.right, expr_tree_expr).Resolve (ec);
 
1978
                                b.type = ReturnType;
 
1979
 
 
1980
                                //
 
1981
                                // Optimize shift by 0
 
1982
                                //
 
1983
                                var c = b.right as Constant;
 
1984
                                if (c != null && c.IsDefaultValue)
 
1985
                                        return ReducedExpression.Create (b.left, b).Resolve (ec);
 
1986
 
 
1987
                                return b;
 
1988
                        }
 
1989
                }
 
1990
 
 
1991
                sealed class PredefinedEqualityOperator : PredefinedOperator
 
1992
                {
 
1993
                        MethodSpec equal_method, inequal_method;
 
1994
 
 
1995
                        public PredefinedEqualityOperator (TypeSpec arg, TypeSpec retType)
 
1996
                                : base (arg, arg, Operator.EqualityMask, retType)
 
1997
                        {
 
1998
                        }
 
1999
 
 
2000
                        public override Expression ConvertResult (ResolveContext ec, Binary b)
 
2001
                        {
 
2002
                                b.type = ReturnType;
 
2003
 
 
2004
                                b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location);
 
2005
                                b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location);
 
2006
 
 
2007
                                Arguments args = new Arguments (2);
 
2008
                                args.Add (new Argument (b.left));
 
2009
                                args.Add (new Argument (b.right));
 
2010
 
 
2011
                                MethodSpec method;
 
2012
                                if (b.oper == Operator.Equality) {
 
2013
                                        if (equal_method == null) {
 
2014
                                                if (left.BuiltinType == BuiltinTypeSpec.Type.String)
 
2015
                                                        equal_method = ec.Module.PredefinedMembers.StringEqual.Resolve (b.loc);
 
2016
                                                else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate)
 
2017
                                                        equal_method = ec.Module.PredefinedMembers.DelegateEqual.Resolve (b.loc);
 
2018
                                                else
 
2019
                                                        throw new NotImplementedException (left.GetSignatureForError ());
 
2020
                                        }
 
2021
 
 
2022
                                        method = equal_method;
 
2023
                                } else {
 
2024
                                        if (inequal_method == null) {
 
2025
                                                if (left.BuiltinType == BuiltinTypeSpec.Type.String)
 
2026
                                                        inequal_method = ec.Module.PredefinedMembers.StringInequal.Resolve (b.loc);
 
2027
                                                else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate)
 
2028
                                                        inequal_method = ec.Module.PredefinedMembers.DelegateInequal.Resolve (b.loc);
 
2029
                                                else
 
2030
                                                        throw new NotImplementedException (left.GetSignatureForError ());
 
2031
                                        }
 
2032
 
 
2033
                                        method = inequal_method;
 
2034
                                }
 
2035
 
 
2036
                                return new UserOperatorCall (method, args, b.CreateExpressionTree, b.loc);
 
2037
                        }
 
2038
                }
 
2039
 
 
2040
                class PredefinedPointerOperator : PredefinedOperator
 
2041
                {
 
2042
                        public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask)
 
2043
                                : base (ltype, rtype, op_mask)
 
2044
                        {
 
2045
                        }
 
2046
 
 
2047
                        public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType)
 
2048
                                : base (ltype, rtype, op_mask, retType)
 
2049
                        {
 
2050
                        }
 
2051
 
 
2052
                        public PredefinedPointerOperator (TypeSpec type, Operator op_mask, TypeSpec return_type)
 
2053
                                : base (type, op_mask, return_type)
 
2054
                        {
 
2055
                        }
 
2056
 
 
2057
                        public override bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr)
 
2058
                        {
 
2059
                                if (left == null) {
 
2060
                                        if (!lexpr.Type.IsPointer)
 
2061
                                                return false;
 
2062
                                } else {
 
2063
                                        if (!Convert.ImplicitConversionExists (ec, lexpr, left))
 
2064
                                                return false;
 
2065
                                }
 
2066
 
 
2067
                                if (right == null) {
 
2068
                                        if (!rexpr.Type.IsPointer)
 
2069
                                                return false;
 
2070
                                } else {
 
2071
                                        if (!Convert.ImplicitConversionExists (ec, rexpr, right))
 
2072
                                                return false;
 
2073
                                }
 
2074
 
 
2075
                                return true;
 
2076
                        }
 
2077
 
 
2078
                        public override Expression ConvertResult (ResolveContext ec, Binary b)
 
2079
                        {
 
2080
                                if (left != null) {
 
2081
                                        b.left = EmptyCast.Create (b.left, left);
 
2082
                                } else if (right != null) {
 
2083
                                        b.right = EmptyCast.Create (b.right, right);
 
2084
                                }
 
2085
 
 
2086
                                TypeSpec r_type = ReturnType;
 
2087
                                Expression left_arg, right_arg;
 
2088
                                if (r_type == null) {
 
2089
                                        if (left == null) {
 
2090
                                                left_arg = b.left;
 
2091
                                                right_arg = b.right;
 
2092
                                                r_type = b.left.Type;
 
2093
                                        } else {
 
2094
                                                left_arg = b.right;
 
2095
                                                right_arg = b.left;
 
2096
                                                r_type = b.right.Type;
 
2097
                                        }
 
2098
                                } else {
 
2099
                                        left_arg = b.left;
 
2100
                                        right_arg = b.right;
 
2101
                                }
 
2102
 
 
2103
                                return new PointerArithmetic (b.oper, left_arg, right_arg, r_type, b.loc).Resolve (ec);
 
2104
                        }
 
2105
                }
 
2106
 
 
2107
                [Flags]
 
2108
                public enum Operator {
 
2109
                        Multiply        = 0 | ArithmeticMask,
 
2110
                        Division        = 1 | ArithmeticMask,
 
2111
                        Modulus         = 2 | ArithmeticMask,
 
2112
                        Addition        = 3 | ArithmeticMask | AdditionMask,
 
2113
                        Subtraction = 4 | ArithmeticMask | SubtractionMask,
 
2114
 
 
2115
                        LeftShift       = 5 | ShiftMask,
 
2116
                        RightShift      = 6 | ShiftMask,
 
2117
 
 
2118
                        LessThan        = 7 | ComparisonMask | RelationalMask,
 
2119
                        GreaterThan     = 8 | ComparisonMask | RelationalMask,
 
2120
                        LessThanOrEqual         = 9 | ComparisonMask | RelationalMask,
 
2121
                        GreaterThanOrEqual      = 10 | ComparisonMask | RelationalMask,
 
2122
                        Equality        = 11 | ComparisonMask | EqualityMask,
 
2123
                        Inequality      = 12 | ComparisonMask | EqualityMask,
 
2124
 
 
2125
                        BitwiseAnd      = 13 | BitwiseMask,
 
2126
                        ExclusiveOr     = 14 | BitwiseMask,
 
2127
                        BitwiseOr       = 15 | BitwiseMask,
 
2128
 
 
2129
                        LogicalAnd      = 16 | LogicalMask,
 
2130
                        LogicalOr       = 17 | LogicalMask,
 
2131
 
 
2132
                        //
 
2133
                        // Operator masks
 
2134
                        //
 
2135
                        ValuesOnlyMask  = ArithmeticMask - 1,
 
2136
                        ArithmeticMask  = 1 << 5,
 
2137
                        ShiftMask               = 1 << 6,
 
2138
                        ComparisonMask  = 1 << 7,
 
2139
                        EqualityMask    = 1 << 8,
 
2140
                        BitwiseMask             = 1 << 9,
 
2141
                        LogicalMask             = 1 << 10,
 
2142
                        AdditionMask    = 1 << 11,
 
2143
                        SubtractionMask = 1 << 12,
 
2144
                        RelationalMask  = 1 << 13
 
2145
                }
 
2146
 
 
2147
                protected enum State
 
2148
                {
 
2149
                        None = 0,
 
2150
                        Compound = 1 << 1,
 
2151
                        LeftNullLifted = 1 << 2,
 
2152
                        RightNullLifted = 1 << 3
 
2153
                }
 
2154
 
 
2155
                readonly Operator oper;
 
2156
                protected Expression left, right;
 
2157
                protected State state;
 
2158
                Expression enum_conversion;
 
2159
 
 
2160
                public Binary (Operator oper, Expression left, Expression right, bool isCompound, Location loc)
 
2161
                        : this (oper, left, right, loc)
 
2162
                {
 
2163
                        if (isCompound)
 
2164
                                state |= State.Compound;
 
2165
                }
 
2166
 
 
2167
                public Binary (Operator oper, Expression left, Expression right, Location loc)
 
2168
                {
 
2169
                        this.oper = oper;
 
2170
                        this.left = left;
 
2171
                        this.right = right;
 
2172
                        this.loc = loc;
 
2173
                }
 
2174
 
 
2175
                #region Properties
 
2176
 
 
2177
                public bool IsCompound {
 
2178
                        get {
 
2179
                                return (state & State.Compound) != 0;
 
2180
                        }
 
2181
                }
 
2182
 
 
2183
                public Operator Oper {
 
2184
                        get {
 
2185
                                return oper;
 
2186
                        }
 
2187
                }
 
2188
 
 
2189
                public Expression Left {
 
2190
                        get { return this.left; }
 
2191
                }
 
2192
 
 
2193
                public Expression Right {
 
2194
                        get { return this.right; }
 
2195
                }
 
2196
 
 
2197
                #endregion
 
2198
 
 
2199
                /// <summary>
 
2200
                ///   Returns a stringified representation of the Operator
 
2201
                /// </summary>
 
2202
                string OperName (Operator oper)
 
2203
                {
 
2204
                        string s;
 
2205
                        switch (oper){
 
2206
                        case Operator.Multiply:
 
2207
                                s = "*";
 
2208
                                break;
 
2209
                        case Operator.Division:
 
2210
                                s = "/";
 
2211
                                break;
 
2212
                        case Operator.Modulus:
 
2213
                                s = "%";
 
2214
                                break;
 
2215
                        case Operator.Addition:
 
2216
                                s = "+";
 
2217
                                break;
 
2218
                        case Operator.Subtraction:
 
2219
                                s = "-";
 
2220
                                break;
 
2221
                        case Operator.LeftShift:
 
2222
                                s = "<<";
 
2223
                                break;
 
2224
                        case Operator.RightShift:
 
2225
                                s = ">>";
 
2226
                                break;
 
2227
                        case Operator.LessThan:
 
2228
                                s = "<";
 
2229
                                break;
 
2230
                        case Operator.GreaterThan:
 
2231
                                s = ">";
 
2232
                                break;
 
2233
                        case Operator.LessThanOrEqual:
 
2234
                                s = "<=";
 
2235
                                break;
 
2236
                        case Operator.GreaterThanOrEqual:
 
2237
                                s = ">=";
 
2238
                                break;
 
2239
                        case Operator.Equality:
 
2240
                                s = "==";
 
2241
                                break;
 
2242
                        case Operator.Inequality:
 
2243
                                s = "!=";
 
2244
                                break;
 
2245
                        case Operator.BitwiseAnd:
 
2246
                                s = "&";
 
2247
                                break;
 
2248
                        case Operator.BitwiseOr:
 
2249
                                s = "|";
 
2250
                                break;
 
2251
                        case Operator.ExclusiveOr:
 
2252
                                s = "^";
 
2253
                                break;
 
2254
                        case Operator.LogicalOr:
 
2255
                                s = "||";
 
2256
                                break;
 
2257
                        case Operator.LogicalAnd:
 
2258
                                s = "&&";
 
2259
                                break;
 
2260
                        default:
 
2261
                                s = oper.ToString ();
 
2262
                                break;
 
2263
                        }
 
2264
 
 
2265
                        if (IsCompound)
 
2266
                                return s + "=";
 
2267
 
 
2268
                        return s;
 
2269
                }
 
2270
 
 
2271
                public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, Operator oper, Location loc)
 
2272
                {
 
2273
                        new Binary (oper, left, right, loc).Error_OperatorCannotBeApplied (ec, left, right);
 
2274
                }
 
2275
 
 
2276
                public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc)
 
2277
                {
 
2278
                        if (left.Type == InternalType.FakeInternalType || right.Type == InternalType.FakeInternalType)
 
2279
                                return;
 
2280
 
 
2281
                        string l, r;
 
2282
                        l = TypeManager.CSharpName (left.Type);
 
2283
                        r = TypeManager.CSharpName (right.Type);
 
2284
 
 
2285
                        ec.Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'",
 
2286
                                oper, l, r);
 
2287
                }
 
2288
                
 
2289
                protected void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right)
 
2290
                {
 
2291
                        Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc);
 
2292
                }
 
2293
 
 
2294
                //
 
2295
                // Converts operator to System.Linq.Expressions.ExpressionType enum name
 
2296
                //
 
2297
                string GetOperatorExpressionTypeName ()
 
2298
                {
 
2299
                        switch (oper) {
 
2300
                        case Operator.Addition:
 
2301
                                return IsCompound ? "AddAssign" : "Add";
 
2302
                        case Operator.BitwiseAnd:
 
2303
                                return IsCompound ? "AndAssign" : "And";
 
2304
                        case Operator.BitwiseOr:
 
2305
                                return IsCompound ? "OrAssign" : "Or";
 
2306
                        case Operator.Division:
 
2307
                                return IsCompound ? "DivideAssign" : "Divide";
 
2308
                        case Operator.ExclusiveOr:
 
2309
                                return IsCompound ? "ExclusiveOrAssign" : "ExclusiveOr";
 
2310
                        case Operator.Equality:
 
2311
                                return "Equal";
 
2312
                        case Operator.GreaterThan:
 
2313
                                return "GreaterThan";
 
2314
                        case Operator.GreaterThanOrEqual:
 
2315
                                return "GreaterThanOrEqual";
 
2316
                        case Operator.Inequality:
 
2317
                                return "NotEqual";
 
2318
                        case Operator.LeftShift:
 
2319
                                return IsCompound ? "LeftShiftAssign" : "LeftShift";
 
2320
                        case Operator.LessThan:
 
2321
                                return "LessThan";
 
2322
                        case Operator.LessThanOrEqual:
 
2323
                                return "LessThanOrEqual";
 
2324
                        case Operator.LogicalAnd:
 
2325
                                return "And";
 
2326
                        case Operator.LogicalOr:
 
2327
                                return "Or";
 
2328
                        case Operator.Modulus:
 
2329
                                return IsCompound ? "ModuloAssign" : "Modulo";
 
2330
                        case Operator.Multiply:
 
2331
                                return IsCompound ? "MultiplyAssign" : "Multiply";
 
2332
                        case Operator.RightShift:
 
2333
                                return IsCompound ? "RightShiftAssign" : "RightShift";
 
2334
                        case Operator.Subtraction:
 
2335
                                return IsCompound ? "SubtractAssign" : "Subtract";
 
2336
                        default:
 
2337
                                throw new NotImplementedException ("Unknown expression type operator " + oper.ToString ());
 
2338
                        }
 
2339
                }
 
2340
 
 
2341
                static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op)
 
2342
                {
 
2343
                        switch (op) {
 
2344
                        case Operator.Addition:
 
2345
                                return CSharp.Operator.OpType.Addition;
 
2346
                        case Operator.BitwiseAnd:
 
2347
                        case Operator.LogicalAnd:
 
2348
                                return CSharp.Operator.OpType.BitwiseAnd;
 
2349
                        case Operator.BitwiseOr:
 
2350
                        case Operator.LogicalOr:
 
2351
                                return CSharp.Operator.OpType.BitwiseOr;
 
2352
                        case Operator.Division:
 
2353
                                return CSharp.Operator.OpType.Division;
 
2354
                        case Operator.Equality:
 
2355
                                return CSharp.Operator.OpType.Equality;
 
2356
                        case Operator.ExclusiveOr:
 
2357
                                return CSharp.Operator.OpType.ExclusiveOr;
 
2358
                        case Operator.GreaterThan:
 
2359
                                return CSharp.Operator.OpType.GreaterThan;
 
2360
                        case Operator.GreaterThanOrEqual:
 
2361
                                return CSharp.Operator.OpType.GreaterThanOrEqual;
 
2362
                        case Operator.Inequality:
 
2363
                                return CSharp.Operator.OpType.Inequality;
 
2364
                        case Operator.LeftShift:
 
2365
                                return CSharp.Operator.OpType.LeftShift;
 
2366
                        case Operator.LessThan:
 
2367
                                return CSharp.Operator.OpType.LessThan;
 
2368
                        case Operator.LessThanOrEqual:
 
2369
                                return CSharp.Operator.OpType.LessThanOrEqual;
 
2370
                        case Operator.Modulus:
 
2371
                                return CSharp.Operator.OpType.Modulus;
 
2372
                        case Operator.Multiply:
 
2373
                                return CSharp.Operator.OpType.Multiply;
 
2374
                        case Operator.RightShift:
 
2375
                                return CSharp.Operator.OpType.RightShift;
 
2376
                        case Operator.Subtraction:
 
2377
                                return CSharp.Operator.OpType.Subtraction;
 
2378
                        default:
 
2379
                                throw new InternalErrorException (op.ToString ());
 
2380
                        }
 
2381
                }
 
2382
 
 
2383
                public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l)
 
2384
                {
 
2385
                        OpCode opcode;
 
2386
 
 
2387
                        switch (oper){
 
2388
                        case Operator.Multiply:
 
2389
                                if (ec.HasSet (EmitContext.Options.CheckedScope)) {
 
2390
                                        if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long)
 
2391
                                                opcode = OpCodes.Mul_Ovf;
 
2392
                                        else if (!IsFloat (l))
 
2393
                                                opcode = OpCodes.Mul_Ovf_Un;
 
2394
                                        else
 
2395
                                                opcode = OpCodes.Mul;
 
2396
                                } else
 
2397
                                        opcode = OpCodes.Mul;
 
2398
                                
 
2399
                                break;
 
2400
                                
 
2401
                        case Operator.Division:
 
2402
                                if (IsUnsigned (l))
 
2403
                                        opcode = OpCodes.Div_Un;
 
2404
                                else
 
2405
                                        opcode = OpCodes.Div;
 
2406
                                break;
 
2407
                                
 
2408
                        case Operator.Modulus:
 
2409
                                if (IsUnsigned (l))
 
2410
                                        opcode = OpCodes.Rem_Un;
 
2411
                                else
 
2412
                                        opcode = OpCodes.Rem;
 
2413
                                break;
 
2414
 
 
2415
                        case Operator.Addition:
 
2416
                                if (ec.HasSet (EmitContext.Options.CheckedScope)) {
 
2417
                                        if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long)
 
2418
                                                opcode = OpCodes.Add_Ovf;
 
2419
                                        else if (!IsFloat (l))
 
2420
                                                opcode = OpCodes.Add_Ovf_Un;
 
2421
                                        else
 
2422
                                                opcode = OpCodes.Add;
 
2423
                                } else
 
2424
                                        opcode = OpCodes.Add;
 
2425
                                break;
 
2426
 
 
2427
                        case Operator.Subtraction:
 
2428
                                if (ec.HasSet (EmitContext.Options.CheckedScope)) {
 
2429
                                        if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long)
 
2430
                                                opcode = OpCodes.Sub_Ovf;
 
2431
                                        else if (!IsFloat (l))
 
2432
                                                opcode = OpCodes.Sub_Ovf_Un;
 
2433
                                        else
 
2434
                                                opcode = OpCodes.Sub;
 
2435
                                } else
 
2436
                                        opcode = OpCodes.Sub;
 
2437
                                break;
 
2438
 
 
2439
                        case Operator.RightShift:
 
2440
                                if (IsUnsigned (l))
 
2441
                                        opcode = OpCodes.Shr_Un;
 
2442
                                else
 
2443
                                        opcode = OpCodes.Shr;
 
2444
                                break;
 
2445
                                
 
2446
                        case Operator.LeftShift:
 
2447
                                opcode = OpCodes.Shl;
 
2448
                                break;
 
2449
 
 
2450
                        case Operator.Equality:
 
2451
                                opcode = OpCodes.Ceq;
 
2452
                                break;
 
2453
 
 
2454
                        case Operator.Inequality:
 
2455
                                ec.Emit (OpCodes.Ceq);
 
2456
                                ec.Emit (OpCodes.Ldc_I4_0);
 
2457
                                
 
2458
                                opcode = OpCodes.Ceq;
 
2459
                                break;
 
2460
 
 
2461
                        case Operator.LessThan:
 
2462
                                if (IsUnsigned (l))
 
2463
                                        opcode = OpCodes.Clt_Un;
 
2464
                                else
 
2465
                                        opcode = OpCodes.Clt;
 
2466
                                break;
 
2467
 
 
2468
                        case Operator.GreaterThan:
 
2469
                                if (IsUnsigned (l))
 
2470
                                        opcode = OpCodes.Cgt_Un;
 
2471
                                else
 
2472
                                        opcode = OpCodes.Cgt;
 
2473
                                break;
 
2474
 
 
2475
                        case Operator.LessThanOrEqual:
 
2476
                                if (IsUnsigned (l) || IsFloat (l))
 
2477
                                        ec.Emit (OpCodes.Cgt_Un);
 
2478
                                else
 
2479
                                        ec.Emit (OpCodes.Cgt);
 
2480
                                ec.Emit (OpCodes.Ldc_I4_0);
 
2481
                                
 
2482
                                opcode = OpCodes.Ceq;
 
2483
                                break;
 
2484
 
 
2485
                        case Operator.GreaterThanOrEqual:
 
2486
                                if (IsUnsigned (l) || IsFloat (l))
 
2487
                                        ec.Emit (OpCodes.Clt_Un);
 
2488
                                else
 
2489
                                        ec.Emit (OpCodes.Clt);
 
2490
                                
 
2491
                                ec.Emit (OpCodes.Ldc_I4_0);
 
2492
                                
 
2493
                                opcode = OpCodes.Ceq;
 
2494
                                break;
 
2495
 
 
2496
                        case Operator.BitwiseOr:
 
2497
                                opcode = OpCodes.Or;
 
2498
                                break;
 
2499
 
 
2500
                        case Operator.BitwiseAnd:
 
2501
                                opcode = OpCodes.And;
 
2502
                                break;
 
2503
 
 
2504
                        case Operator.ExclusiveOr:
 
2505
                                opcode = OpCodes.Xor;
 
2506
                                break;
 
2507
 
 
2508
                        default:
 
2509
                                throw new InternalErrorException (oper.ToString ());
 
2510
                        }
 
2511
 
 
2512
                        ec.Emit (opcode);
 
2513
                }
 
2514
 
 
2515
                static bool IsUnsigned (TypeSpec t)
 
2516
                {
 
2517
                        switch (t.BuiltinType) {
 
2518
                        case BuiltinTypeSpec.Type.Char:
 
2519
                        case BuiltinTypeSpec.Type.UInt:
 
2520
                        case BuiltinTypeSpec.Type.ULong:
 
2521
                        case BuiltinTypeSpec.Type.UShort:
 
2522
                        case BuiltinTypeSpec.Type.Byte:
 
2523
                                return true;
 
2524
                        }
 
2525
 
 
2526
                        return t.IsPointer;
 
2527
                }
 
2528
 
 
2529
                static bool IsFloat (TypeSpec t)
 
2530
                {
 
2531
                        return t.BuiltinType == BuiltinTypeSpec.Type.Float || t.BuiltinType == BuiltinTypeSpec.Type.Double;
 
2532
                }
 
2533
 
 
2534
                Expression ResolveOperator (ResolveContext ec)
 
2535
                {
 
2536
                        TypeSpec l = left.Type;
 
2537
                        TypeSpec r = right.Type;
 
2538
                        Expression expr;
 
2539
                        bool primitives_only = false;
 
2540
 
 
2541
                        //
 
2542
                        // Handles predefined primitive types
 
2543
                        //
 
2544
                        if (BuiltinTypeSpec.IsPrimitiveType (l) && BuiltinTypeSpec.IsPrimitiveType (r)) {
 
2545
                                if ((oper & Operator.ShiftMask) == 0) {
 
2546
                                        if (l.BuiltinType != BuiltinTypeSpec.Type.Bool && !DoBinaryOperatorPromotion (ec))
 
2547
                                                return null;
 
2548
 
 
2549
                                        primitives_only = true;
 
2550
                                }
 
2551
                        } else {
 
2552
                                // Pointers
 
2553
                                if (l.IsPointer || r.IsPointer)
 
2554
                                        return ResolveOperatorPointer (ec, l, r);
 
2555
 
 
2556
                                // Enums
 
2557
                                bool lenum = l.IsEnum;
 
2558
                                bool renum = r.IsEnum;
 
2559
                                if (lenum || renum) {
 
2560
                                        expr = ResolveOperatorEnum (ec, lenum, renum, l, r);
 
2561
 
 
2562
                                        if (expr != null)
 
2563
                                                return expr;
 
2564
                                }
 
2565
 
 
2566
                                // Delegates
 
2567
                                if ((oper == Operator.Addition || oper == Operator.Subtraction) && (l.IsDelegate || r.IsDelegate)) {
 
2568
                                                
 
2569
                                        expr = ResolveOperatorDelegate (ec, l, r);
 
2570
 
 
2571
                                        // TODO: Can this be ambiguous
 
2572
                                        if (expr != null)
 
2573
                                                return expr;
 
2574
                                }
 
2575
 
 
2576
                                // User operators
 
2577
                                expr = ResolveUserOperator (ec, left, right);
 
2578
                                if (expr != null)
 
2579
                                        return expr;
 
2580
 
 
2581
                                // Predefined reference types equality
 
2582
                                if ((oper & Operator.EqualityMask) != 0) {
 
2583
                                        expr = ResolveOperatorEquality (ec, l, r);
 
2584
                                        if (expr != null)
 
2585
                                                return expr;
 
2586
                                }
 
2587
                        }
 
2588
 
 
2589
                        return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryStandard, primitives_only, null);
 
2590
                }
 
2591
 
 
2592
                // at least one of 'left' or 'right' is an enumeration constant (EnumConstant or SideEffectConstant or ...)
 
2593
                // if 'left' is not an enumeration constant, create one from the type of 'right'
 
2594
                Constant EnumLiftUp (ResolveContext ec, Constant left, Constant right, Location loc)
 
2595
                {
 
2596
                        switch (oper) {
 
2597
                        case Operator.BitwiseOr:
 
2598
                        case Operator.BitwiseAnd:
 
2599
                        case Operator.ExclusiveOr:
 
2600
                        case Operator.Equality:
 
2601
                        case Operator.Inequality:
 
2602
                        case Operator.LessThan:
 
2603
                        case Operator.LessThanOrEqual:
 
2604
                        case Operator.GreaterThan:
 
2605
                        case Operator.GreaterThanOrEqual:
 
2606
                                if (TypeManager.IsEnumType (left.Type))
 
2607
                                        return left;
 
2608
                                
 
2609
                                if (left.IsZeroInteger)
 
2610
                                        return left.TryReduce (ec, right.Type, loc);
 
2611
                                
 
2612
                                break;
 
2613
                                
 
2614
                        case Operator.Addition:
 
2615
                        case Operator.Subtraction:
 
2616
                                return left;
 
2617
                                
 
2618
                        case Operator.Multiply:
 
2619
                        case Operator.Division:
 
2620
                        case Operator.Modulus:
 
2621
                        case Operator.LeftShift:
 
2622
                        case Operator.RightShift:
 
2623
                                if (TypeManager.IsEnumType (right.Type) || TypeManager.IsEnumType (left.Type))
 
2624
                                        break;
 
2625
                                return left;
 
2626
                        }
 
2627
 
 
2628
                        return null;
 
2629
                }
 
2630
 
 
2631
                //
 
2632
                // The `|' operator used on types which were extended is dangerous
 
2633
                //
 
2634
                void CheckBitwiseOrOnSignExtended (ResolveContext ec)
 
2635
                {
 
2636
                        OpcodeCast lcast = left as OpcodeCast;
 
2637
                        if (lcast != null) {
 
2638
                                if (IsUnsigned (lcast.UnderlyingType))
 
2639
                                        lcast = null;
 
2640
                        }
 
2641
 
 
2642
                        OpcodeCast rcast = right as OpcodeCast;
 
2643
                        if (rcast != null) {
 
2644
                                if (IsUnsigned (rcast.UnderlyingType))
 
2645
                                        rcast = null;
 
2646
                        }
 
2647
 
 
2648
                        if (lcast == null && rcast == null)
 
2649
                                return;
 
2650
 
 
2651
                        // FIXME: consider constants
 
2652
 
 
2653
                        ec.Report.Warning (675, 3, loc,
 
2654
                                "The operator `|' used on the sign-extended type `{0}'. Consider casting to a smaller unsigned type first",
 
2655
                                TypeManager.CSharpName (lcast != null ? lcast.UnderlyingType : rcast.UnderlyingType));
 
2656
                }
 
2657
 
 
2658
                public static PredefinedOperator[] CreatePointerOperatorsTable (BuiltinTypes types)
 
2659
                {
 
2660
                        return new PredefinedOperator[] {
 
2661
                                //
 
2662
                                // Pointer arithmetic:
 
2663
                                //
 
2664
                                // T* operator + (T* x, int y);         T* operator - (T* x, int y);
 
2665
                                // T* operator + (T* x, uint y);        T* operator - (T* x, uint y);
 
2666
                                // T* operator + (T* x, long y);        T* operator - (T* x, long y);
 
2667
                                // T* operator + (T* x, ulong y);       T* operator - (T* x, ulong y);
 
2668
                                //
 
2669
                                new PredefinedPointerOperator (null, types.Int, Operator.AdditionMask | Operator.SubtractionMask),
 
2670
                                new PredefinedPointerOperator (null, types.UInt, Operator.AdditionMask | Operator.SubtractionMask),
 
2671
                                new PredefinedPointerOperator (null, types.Long, Operator.AdditionMask | Operator.SubtractionMask),
 
2672
                                new PredefinedPointerOperator (null, types.ULong, Operator.AdditionMask | Operator.SubtractionMask),
 
2673
 
 
2674
                                //
 
2675
                                // T* operator + (int y,   T* x);
 
2676
                                // T* operator + (uint y,  T *x);
 
2677
                                // T* operator + (long y,  T *x);
 
2678
                                // T* operator + (ulong y, T *x);
 
2679
                                //
 
2680
                                new PredefinedPointerOperator (types.Int, null, Operator.AdditionMask, null),
 
2681
                                new PredefinedPointerOperator (types.UInt, null, Operator.AdditionMask, null),
 
2682
                                new PredefinedPointerOperator (types.Long, null, Operator.AdditionMask, null),
 
2683
                                new PredefinedPointerOperator (types.ULong, null, Operator.AdditionMask, null),
 
2684
 
 
2685
                                //
 
2686
                                // long operator - (T* x, T *y)
 
2687
                                //
 
2688
                                new PredefinedPointerOperator (null, Operator.SubtractionMask, types.Long)
 
2689
                        };
 
2690
                }
 
2691
 
 
2692
                public static PredefinedOperator[] CreateStandardOperatorsTable (BuiltinTypes types)
 
2693
                {
 
2694
                        TypeSpec bool_type = types.Bool;
 
2695
                        return new PredefinedOperator[] {
 
2696
                                new PredefinedOperator (types.Int, Operator.ArithmeticMask | Operator.BitwiseMask),
 
2697
                                new PredefinedOperator (types.UInt, Operator.ArithmeticMask | Operator.BitwiseMask),
 
2698
                                new PredefinedOperator (types.Long, Operator.ArithmeticMask | Operator.BitwiseMask),
 
2699
                                new PredefinedOperator (types.ULong, Operator.ArithmeticMask | Operator.BitwiseMask),
 
2700
                                new PredefinedOperator (types.Float, Operator.ArithmeticMask),
 
2701
                                new PredefinedOperator (types.Double, Operator.ArithmeticMask),
 
2702
                                new PredefinedOperator (types.Decimal, Operator.ArithmeticMask),
 
2703
 
 
2704
                                new PredefinedOperator (types.Int, Operator.ComparisonMask, bool_type),
 
2705
                                new PredefinedOperator (types.UInt, Operator.ComparisonMask, bool_type),
 
2706
                                new PredefinedOperator (types.Long, Operator.ComparisonMask, bool_type),
 
2707
                                new PredefinedOperator (types.ULong, Operator.ComparisonMask, bool_type),
 
2708
                                new PredefinedOperator (types.Float, Operator.ComparisonMask, bool_type),
 
2709
                                new PredefinedOperator (types.Double, Operator.ComparisonMask, bool_type),
 
2710
                                new PredefinedOperator (types.Decimal, Operator.ComparisonMask, bool_type),
 
2711
 
 
2712
                                new PredefinedStringOperator (types.String, Operator.AdditionMask, types.String),
 
2713
                                new PredefinedStringOperator (types.String, types.Object, Operator.AdditionMask, types.String),
 
2714
                                new PredefinedStringOperator (types.Object, types.String, Operator.AdditionMask, types.String),
 
2715
 
 
2716
                                new PredefinedOperator (bool_type, Operator.BitwiseMask | Operator.LogicalMask | Operator.EqualityMask, bool_type),
 
2717
 
 
2718
                                new PredefinedShiftOperator (types.Int, types.Int, Operator.ShiftMask),
 
2719
                                new PredefinedShiftOperator (types.UInt, types.Int, Operator.ShiftMask),
 
2720
                                new PredefinedShiftOperator (types.Long, types.Int, Operator.ShiftMask),
 
2721
                                new PredefinedShiftOperator (types.ULong, types.Int, Operator.ShiftMask)
 
2722
                        };
 
2723
                }
 
2724
 
 
2725
                public static PredefinedOperator[] CreateEqualityOperatorsTable (BuiltinTypes types)
 
2726
                {
 
2727
                        TypeSpec bool_type = types.Bool;
 
2728
 
 
2729
                        return new PredefinedOperator[] {
 
2730
                                new PredefinedEqualityOperator (types.String, bool_type),
 
2731
                                new PredefinedEqualityOperator (types.Delegate, bool_type),
 
2732
                                new PredefinedOperator (bool_type, Operator.EqualityMask, bool_type)
 
2733
                        };
 
2734
                }
 
2735
 
 
2736
                //
 
2737
                // Rules used during binary numeric promotion
 
2738
                //
 
2739
                static bool DoNumericPromotion (ResolveContext rc, ref Expression prim_expr, ref Expression second_expr, TypeSpec type)
 
2740
                {
 
2741
                        Expression temp;
 
2742
 
 
2743
                        Constant c = prim_expr as Constant;
 
2744
                        if (c != null) {
 
2745
                                temp = c.ConvertImplicitly (type);
 
2746
                                if (temp != null) {
 
2747
                                        prim_expr = temp;
 
2748
                                        return true;
 
2749
                                }
 
2750
                        }
 
2751
 
 
2752
                        if (type.BuiltinType == BuiltinTypeSpec.Type.UInt) {
 
2753
                                switch (prim_expr.Type.BuiltinType) {
 
2754
                                case BuiltinTypeSpec.Type.Int:
 
2755
                                case BuiltinTypeSpec.Type.Short:
 
2756
                                case BuiltinTypeSpec.Type.SByte:
 
2757
                                case BuiltinTypeSpec.Type.Long:
 
2758
                                        type = rc.BuiltinTypes.Long;
 
2759
 
 
2760
                                        if (type != second_expr.Type) {
 
2761
                                                c = second_expr as Constant;
 
2762
                                                if (c != null)
 
2763
                                                        temp = c.ConvertImplicitly (type);
 
2764
                                                else
 
2765
                                                        temp = Convert.ImplicitNumericConversion (second_expr, type);
 
2766
                                                if (temp == null)
 
2767
                                                        return false;
 
2768
                                                second_expr = temp;
 
2769
                                        }
 
2770
                                        break;
 
2771
                                }
 
2772
                        } else if (type.BuiltinType == BuiltinTypeSpec.Type.ULong) {
 
2773
                                //
 
2774
                                // A compile-time error occurs if the other operand is of type sbyte, short, int, or long
 
2775
                                //
 
2776
                                switch (type.BuiltinType) {
 
2777
                                case BuiltinTypeSpec.Type.Int:
 
2778
                                case BuiltinTypeSpec.Type.Long:
 
2779
                                case BuiltinTypeSpec.Type.Short:
 
2780
                                case BuiltinTypeSpec.Type.SByte:
 
2781
                                        return false;
 
2782
                                }
 
2783
                        }
 
2784
 
 
2785
                        temp = Convert.ImplicitNumericConversion (prim_expr, type);
 
2786
                        if (temp == null)
 
2787
                                return false;
 
2788
 
 
2789
                        prim_expr = temp;
 
2790
                        return true;
 
2791
                }
 
2792
 
 
2793
                //
 
2794
                // 7.2.6.2 Binary numeric promotions
 
2795
                //
 
2796
                public bool DoBinaryOperatorPromotion (ResolveContext ec)
 
2797
                {
 
2798
                        TypeSpec ltype = left.Type;
 
2799
                        TypeSpec rtype = right.Type;
 
2800
                        Expression temp;
 
2801
 
 
2802
                        foreach (TypeSpec t in ec.BuiltinTypes.BinaryPromotionsTypes) {
 
2803
                                if (t == ltype)
 
2804
                                        return t == rtype || DoNumericPromotion (ec, ref right, ref left, t);
 
2805
 
 
2806
                                if (t == rtype)
 
2807
                                        return t == ltype || DoNumericPromotion (ec, ref left, ref right, t);
 
2808
                        }
 
2809
 
 
2810
                        TypeSpec int32 = ec.BuiltinTypes.Int;
 
2811
                        if (ltype != int32) {
 
2812
                                Constant c = left as Constant;
 
2813
                                if (c != null)
 
2814
                                        temp = c.ConvertImplicitly (int32);
 
2815
                                else
 
2816
                                        temp = Convert.ImplicitNumericConversion (left, int32);
 
2817
 
 
2818
                                if (temp == null)
 
2819
                                        return false;
 
2820
                                left = temp;
 
2821
                        }
 
2822
 
 
2823
                        if (rtype != int32) {
 
2824
                                Constant c = right as Constant;
 
2825
                                if (c != null)
 
2826
                                        temp = c.ConvertImplicitly (int32);
 
2827
                                else
 
2828
                                        temp = Convert.ImplicitNumericConversion (right, int32);
 
2829
 
 
2830
                                if (temp == null)
 
2831
                                        return false;
 
2832
                                right = temp;
 
2833
                        }
 
2834
 
 
2835
                        return true;
 
2836
                }
 
2837
 
 
2838
                protected override Expression DoResolve (ResolveContext ec)
 
2839
                {
 
2840
                        if (left == null)
 
2841
                                return null;
 
2842
 
 
2843
                        if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
 
2844
                                left = ((ParenthesizedExpression) left).Expr;
 
2845
                                left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
 
2846
                                if (left == null)
 
2847
                                        return null;
 
2848
 
 
2849
                                if (left.eclass == ExprClass.Type) {
 
2850
                                        ec.Report.Error (75, loc, "To cast a negative value, you must enclose the value in parentheses");
 
2851
                                        return null;
 
2852
                                }
 
2853
                        } else
 
2854
                                left = left.Resolve (ec);
 
2855
 
 
2856
                        if (left == null)
 
2857
                                return null;
 
2858
 
 
2859
                        Constant lc = left as Constant;
 
2860
 
 
2861
                        if (lc != null && lc.Type.BuiltinType == BuiltinTypeSpec.Type.Bool &&
 
2862
                                ((oper == Operator.LogicalAnd && lc.IsDefaultValue) ||
 
2863
                                 (oper == Operator.LogicalOr && !lc.IsDefaultValue))) {
 
2864
 
 
2865
                                // FIXME: resolve right expression as unreachable
 
2866
                                // right.Resolve (ec);
 
2867
 
 
2868
                                ec.Report.Warning (429, 4, loc, "Unreachable expression code detected");
 
2869
                                return left;
 
2870
                        }
 
2871
 
 
2872
                        right = right.Resolve (ec);
 
2873
                        if (right == null)
 
2874
                                return null;
 
2875
 
 
2876
                        eclass = ExprClass.Value;
 
2877
                        Constant rc = right as Constant;
 
2878
 
 
2879
                        // The conversion rules are ignored in enum context but why
 
2880
                        if (!ec.HasSet (ResolveContext.Options.EnumScope) && lc != null && rc != null && (TypeManager.IsEnumType (left.Type) || TypeManager.IsEnumType (right.Type))) {
 
2881
                                lc = EnumLiftUp (ec, lc, rc, loc);
 
2882
                                if (lc != null)
 
2883
                                        rc = EnumLiftUp (ec, rc, lc, loc);
 
2884
                        }
 
2885
 
 
2886
                        if (rc != null && lc != null) {
 
2887
                                int prev_e = ec.Report.Errors;
 
2888
                                Expression e = ConstantFold.BinaryFold (ec, oper, lc, rc, loc);
 
2889
                                if (e != null || ec.Report.Errors != prev_e)
 
2890
                                        return e;
 
2891
                        }
 
2892
 
 
2893
                        // Comparison warnings
 
2894
                        if ((oper & Operator.ComparisonMask) != 0) {
 
2895
                                if (left.Equals (right)) {
 
2896
                                        ec.Report.Warning (1718, 3, loc, "A comparison made to same variable. Did you mean to compare something else?");
 
2897
                                }
 
2898
                                CheckOutOfRangeComparison (ec, lc, right.Type);
 
2899
                                CheckOutOfRangeComparison (ec, rc, left.Type);
 
2900
                        }
 
2901
 
 
2902
                        if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic || right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
2903
                                var lt = left.Type;
 
2904
                                var rt = right.Type;
 
2905
                                if (lt.Kind == MemberKind.Void || lt == InternalType.MethodGroup || lt == InternalType.AnonymousMethod ||
 
2906
                                        rt.Kind == MemberKind.Void || rt == InternalType.MethodGroup || rt == InternalType.AnonymousMethod) {
 
2907
                                        Error_OperatorCannotBeApplied (ec, left, right);
 
2908
                                        return null;
 
2909
                                }
 
2910
 
 
2911
                                Arguments args;
 
2912
 
 
2913
                                //
 
2914
                                // Special handling for logical boolean operators which require rhs not to be
 
2915
                                // evaluated based on lhs value
 
2916
                                //
 
2917
                                if ((oper & Operator.LogicalMask) != 0) {
 
2918
                                        Expression cond_left, cond_right, expr;
 
2919
 
 
2920
                                        args = new Arguments (2);
 
2921
 
 
2922
                                        if (lt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
2923
                                                LocalVariable temp = LocalVariable.CreateCompilerGenerated (lt, ec.CurrentBlock, loc);
 
2924
 
 
2925
                                                var cond_args = new Arguments (1);
 
2926
                                                cond_args.Add (new Argument (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left).Resolve (ec)));
 
2927
 
 
2928
                                                //
 
2929
                                                // dynamic && bool => IsFalse (temp = left) ? temp : temp && right;
 
2930
                                                // dynamic || bool => IsTrue (temp = left) ? temp : temp || right;
 
2931
                                                //
 
2932
                                                left = temp.CreateReferenceExpression (ec, loc);
 
2933
                                                if (oper == Operator.LogicalAnd) {
 
2934
                                                        expr = DynamicUnaryConversion.CreateIsFalse (ec, cond_args, loc);
 
2935
                                                        cond_left = left;
 
2936
                                                } else {
 
2937
                                                        expr = DynamicUnaryConversion.CreateIsTrue (ec, cond_args, loc);
 
2938
                                                        cond_left = left;
 
2939
                                                }
 
2940
 
 
2941
                                                args.Add (new Argument (left));
 
2942
                                                args.Add (new Argument (right));
 
2943
                                                cond_right = new DynamicExpressionStatement (this, args, loc);
 
2944
                                        } else {
 
2945
                                                LocalVariable temp = LocalVariable.CreateCompilerGenerated (ec.BuiltinTypes.Bool, ec.CurrentBlock, loc);
 
2946
 
 
2947
                                                args.Add (new Argument (temp.CreateReferenceExpression (ec, loc).Resolve (ec)));
 
2948
                                                args.Add (new Argument (right));
 
2949
                                                right = new DynamicExpressionStatement (this, args, loc);
 
2950
 
 
2951
                                                //
 
2952
                                                // bool && dynamic => (temp = left) ? temp && right : temp;
 
2953
                                                // bool || dynamic => (temp = left) ? temp : temp || right;
 
2954
                                                //
 
2955
                                                if (oper == Operator.LogicalAnd) {
 
2956
                                                        cond_left = right;
 
2957
                                                        cond_right = temp.CreateReferenceExpression (ec, loc);
 
2958
                                                } else {
 
2959
                                                        cond_left = temp.CreateReferenceExpression (ec, loc);
 
2960
                                                        cond_right = right;
 
2961
                                                }
 
2962
 
 
2963
                                                expr = new BooleanExpression (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left));
 
2964
                                        }
 
2965
 
 
2966
                                        return new Conditional (expr, cond_left, cond_right, loc).Resolve (ec);
 
2967
                                }
 
2968
 
 
2969
                                args = new Arguments (2);
 
2970
                                args.Add (new Argument (left));
 
2971
                                args.Add (new Argument (right));
 
2972
                                return new DynamicExpressionStatement (this, args, loc).Resolve (ec);
 
2973
                        }
 
2974
 
 
2975
                        if (ec.Module.Compiler.Settings.Version >= LanguageVersion.ISO_2 &&
 
2976
                                ((left.Type.IsNullableType && (right is NullLiteral || right.Type.IsNullableType || TypeSpec.IsValueType (right.Type))) ||
 
2977
                                (TypeSpec.IsValueType (left.Type) && right is NullLiteral) ||
 
2978
                                (right.Type.IsNullableType && (left is NullLiteral || left.Type.IsNullableType || TypeSpec.IsValueType (left.Type))) ||
 
2979
                                (TypeSpec.IsValueType (right.Type) && left is NullLiteral))) {
 
2980
                                var lifted = new Nullable.LiftedBinaryOperator (oper, left, right, loc);
 
2981
                                lifted.state = state;
 
2982
                                return lifted.Resolve (ec);
 
2983
                        }
 
2984
 
 
2985
                        return DoResolveCore (ec, left, right);
 
2986
                }
 
2987
 
 
2988
                protected Expression DoResolveCore (ResolveContext ec, Expression left_orig, Expression right_orig)
 
2989
                {
 
2990
                        Expression expr = ResolveOperator (ec);
 
2991
                        if (expr == null)
 
2992
                                Error_OperatorCannotBeApplied (ec, left_orig, right_orig);
 
2993
 
 
2994
                        if (left == null || right == null)
 
2995
                                throw new InternalErrorException ("Invalid conversion");
 
2996
 
 
2997
                        if (oper == Operator.BitwiseOr)
 
2998
                                CheckBitwiseOrOnSignExtended (ec);
 
2999
 
 
3000
                        return expr;
 
3001
                }
 
3002
 
 
3003
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
3004
                {
 
3005
                        var le = left.MakeExpression (ctx);
 
3006
                        var re = right.MakeExpression (ctx);
 
3007
                        bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope);
 
3008
 
 
3009
                        switch (oper) {
 
3010
                        case Operator.Addition:
 
3011
                                return is_checked ? SLE.Expression.AddChecked (le, re) : SLE.Expression.Add (le, re);
 
3012
                        case Operator.BitwiseAnd:
 
3013
                                return SLE.Expression.And (le, re);
 
3014
                        case Operator.BitwiseOr:
 
3015
                                return SLE.Expression.Or (le, re);
 
3016
                        case Operator.Division:
 
3017
                                return SLE.Expression.Divide (le, re);
 
3018
                        case Operator.Equality:
 
3019
                                return SLE.Expression.Equal (le, re);
 
3020
                        case Operator.ExclusiveOr:
 
3021
                                return SLE.Expression.ExclusiveOr (le, re);
 
3022
                        case Operator.GreaterThan:
 
3023
                                return SLE.Expression.GreaterThan (le, re);
 
3024
                        case Operator.GreaterThanOrEqual:
 
3025
                                return SLE.Expression.GreaterThanOrEqual (le, re);
 
3026
                        case Operator.Inequality:
 
3027
                                return SLE.Expression.NotEqual (le, re);
 
3028
                        case Operator.LeftShift:
 
3029
                                return SLE.Expression.LeftShift (le, re);
 
3030
                        case Operator.LessThan:
 
3031
                                return SLE.Expression.LessThan (le, re);
 
3032
                        case Operator.LessThanOrEqual:
 
3033
                                return SLE.Expression.LessThanOrEqual (le, re);
 
3034
                        case Operator.LogicalAnd:
 
3035
                                return SLE.Expression.AndAlso (le, re);
 
3036
                        case Operator.LogicalOr:
 
3037
                                return SLE.Expression.OrElse (le, re);
 
3038
                        case Operator.Modulus:
 
3039
                                return SLE.Expression.Modulo (le, re);
 
3040
                        case Operator.Multiply:
 
3041
                                return is_checked ? SLE.Expression.MultiplyChecked (le, re) : SLE.Expression.Multiply (le, re);
 
3042
                        case Operator.RightShift:
 
3043
                                return SLE.Expression.RightShift (le, re);
 
3044
                        case Operator.Subtraction:
 
3045
                                return is_checked ? SLE.Expression.SubtractChecked (le, re) : SLE.Expression.Subtract (le, re);
 
3046
                        default:
 
3047
                                throw new NotImplementedException (oper.ToString ());
 
3048
                        }
 
3049
                }
 
3050
 
 
3051
                //
 
3052
                // D operator + (D x, D y)
 
3053
                // D operator - (D x, D y)
 
3054
                //
 
3055
                Expression ResolveOperatorDelegate (ResolveContext ec, TypeSpec l, TypeSpec r)
 
3056
                {
 
3057
                        if (l != r && !TypeSpecComparer.Variant.IsEqual (r, l)) {
 
3058
                                Expression tmp;
 
3059
                                if (right.eclass == ExprClass.MethodGroup || r == InternalType.AnonymousMethod || r == InternalType.NullLiteral) {
 
3060
                                        tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
 
3061
                                        if (tmp == null)
 
3062
                                                return null;
 
3063
                                        right = tmp;
 
3064
                                        r = right.Type;
 
3065
                                } else if (left.eclass == ExprClass.MethodGroup || (l == InternalType.AnonymousMethod || l == InternalType.NullLiteral)) {
 
3066
                                        tmp = Convert.ImplicitConversionRequired (ec, left, r, loc);
 
3067
                                        if (tmp == null)
 
3068
                                                return null;
 
3069
                                        left = tmp;
 
3070
                                        l = left.Type;
 
3071
                                } else {
 
3072
                                        return null;
 
3073
                                }
 
3074
                        }
 
3075
 
 
3076
                        MethodSpec method = null;
 
3077
                        Arguments args = new Arguments (2);
 
3078
                        args.Add (new Argument (left));
 
3079
                        args.Add (new Argument (right));
 
3080
 
 
3081
                        if (oper == Operator.Addition) {
 
3082
                                method = ec.Module.PredefinedMembers.DelegateCombine.Resolve (loc);
 
3083
                        } else if (oper == Operator.Subtraction) {
 
3084
                                method = ec.Module.PredefinedMembers.DelegateRemove.Resolve (loc);
 
3085
                        }
 
3086
 
 
3087
                        if (method == null)
 
3088
                                return new EmptyExpression (ec.BuiltinTypes.Decimal);
 
3089
 
 
3090
                        MethodGroupExpr mg = MethodGroupExpr.CreatePredefined (method, ec.BuiltinTypes.Delegate, loc);
 
3091
                        Expression expr = new UserOperatorCall (mg.BestCandidate, args, CreateExpressionTree, loc);
 
3092
                        return new ClassCast (expr, l);
 
3093
                }
 
3094
 
 
3095
                //
 
3096
                // Enumeration operators
 
3097
                //
 
3098
                Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype)
 
3099
                {
 
3100
                        //
 
3101
                        // bool operator == (E x, E y);
 
3102
                        // bool operator != (E x, E y);
 
3103
                        // bool operator < (E x, E y);
 
3104
                        // bool operator > (E x, E y);
 
3105
                        // bool operator <= (E x, E y);
 
3106
                        // bool operator >= (E x, E y);
 
3107
                        //
 
3108
                        // E operator & (E x, E y);
 
3109
                        // E operator | (E x, E y);
 
3110
                        // E operator ^ (E x, E y);
 
3111
                        //
 
3112
                        // U operator - (E e, E f)
 
3113
                        // E operator - (E e, U x)
 
3114
                        // E operator - (U x, E e)      // LAMESPEC: Not covered by the specification
 
3115
                        //
 
3116
                        // E operator + (E e, U x)
 
3117
                        // E operator + (U x, E e)
 
3118
                        //
 
3119
                        Expression ltemp = left;
 
3120
                        Expression rtemp = right;
 
3121
                        TypeSpec underlying_type;
 
3122
                        TypeSpec underlying_type_result;
 
3123
                        TypeSpec res_type;
 
3124
                        Expression expr;
 
3125
                        
 
3126
                        //
 
3127
                        // LAMESPEC: There is never ambiguous conversion between enum operators
 
3128
                        // the one which contains more enum parameters always wins even if there
 
3129
                        // is an implicit conversion involved
 
3130
                        //
 
3131
                        if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) {
 
3132
                                if (renum) {
 
3133
                                        underlying_type = EnumSpec.GetUnderlyingType (rtype);
 
3134
                                        expr = Convert.ImplicitConversion (ec, left, rtype, loc);
 
3135
                                        if (expr == null)
 
3136
                                                return null;
 
3137
 
 
3138
                                        left = expr;
 
3139
                                        ltype = expr.Type;
 
3140
                                } else if (lenum) {
 
3141
                                        underlying_type = EnumSpec.GetUnderlyingType (ltype);
 
3142
                                        expr = Convert.ImplicitConversion (ec, right, ltype, loc);
 
3143
                                        if (expr == null)
 
3144
                                                return null;
 
3145
 
 
3146
                                        right = expr;
 
3147
                                        rtype = expr.Type;
 
3148
                                } else {
 
3149
                                        return null;
 
3150
                                }
 
3151
 
 
3152
                                if ((oper & Operator.BitwiseMask) != 0) {
 
3153
                                        res_type = ltype;
 
3154
                                        underlying_type_result = underlying_type;
 
3155
                                } else {
 
3156
                                        res_type = null;
 
3157
                                        underlying_type_result = null;
 
3158
                                }
 
3159
                        } else if (oper == Operator.Subtraction) {
 
3160
                                if (renum) {
 
3161
                                        underlying_type = EnumSpec.GetUnderlyingType (rtype);
 
3162
                                        if (ltype != rtype) {
 
3163
                                                expr = Convert.ImplicitConversion (ec, left, rtype, left.Location);
 
3164
                                                if (expr == null) {
 
3165
                                                        expr = Convert.ImplicitConversion (ec, left, underlying_type, left.Location);
 
3166
                                                        if (expr == null)
 
3167
                                                                return null;
 
3168
 
 
3169
                                                        res_type = rtype;
 
3170
                                                } else {
 
3171
                                                        res_type = underlying_type;
 
3172
                                                }
 
3173
 
 
3174
                                                left = expr;
 
3175
                                        } else {
 
3176
                                                res_type = underlying_type;
 
3177
                                        }
 
3178
 
 
3179
                                        underlying_type_result = underlying_type;
 
3180
                                } else if (lenum) {
 
3181
                                        underlying_type = EnumSpec.GetUnderlyingType (ltype);
 
3182
                                        expr = Convert.ImplicitConversion (ec, right, ltype, right.Location);
 
3183
                                        if (expr == null || expr is EnumConstant) {
 
3184
                                                expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location);
 
3185
                                                if (expr == null)
 
3186
                                                        return null;
 
3187
 
 
3188
                                                res_type = ltype;
 
3189
                                        } else {
 
3190
                                                res_type = underlying_type;
 
3191
                                        }
 
3192
 
 
3193
                                        right = expr;
 
3194
                                        underlying_type_result = underlying_type;
 
3195
                                } else {
 
3196
                                        return null;
 
3197
                                }
 
3198
                        } else if (oper == Operator.Addition) {
 
3199
                                if (lenum) {
 
3200
                                        underlying_type = EnumSpec.GetUnderlyingType (ltype);
 
3201
                                        res_type = ltype;
 
3202
 
 
3203
                                        if (rtype != underlying_type && (state & (State.RightNullLifted | State.LeftNullLifted)) == 0) {
 
3204
                                                expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location);
 
3205
                                                if (expr == null)
 
3206
                                                        return null;
 
3207
 
 
3208
                                                right = expr;
 
3209
                                        }
 
3210
                                } else {
 
3211
                                        underlying_type = EnumSpec.GetUnderlyingType (rtype);
 
3212
                                        res_type = rtype;
 
3213
                                        if (ltype != underlying_type) {
 
3214
                                                expr = Convert.ImplicitConversion (ec, left, underlying_type, left.Location);
 
3215
                                                if (expr == null)
 
3216
                                                        return null;
 
3217
 
 
3218
                                                left = expr;
 
3219
                                        }
 
3220
                                }
 
3221
 
 
3222
                                underlying_type_result = underlying_type;
 
3223
                        } else {
 
3224
                                return null;
 
3225
                        }
 
3226
 
 
3227
                        // Unwrap the constant correctly, so DoBinaryOperatorPromotion can do the magic
 
3228
                        // with constants and expressions
 
3229
                        if (left.Type != underlying_type) {
 
3230
                                if (left is Constant)
 
3231
                                        left = ((Constant) left).ConvertExplicitly (false, underlying_type);
 
3232
                                else
 
3233
                                        left = EmptyCast.Create (left, underlying_type);
 
3234
                        }
 
3235
 
 
3236
                        if (right.Type != underlying_type) {
 
3237
                                if (right is Constant)
 
3238
                                        right = ((Constant) right).ConvertExplicitly (false, underlying_type);
 
3239
                                else
 
3240
                                        right = EmptyCast.Create (right, underlying_type);
 
3241
                        }
 
3242
 
 
3243
                        //
 
3244
                        // C# specification uses explicit cast syntax which means binary promotion
 
3245
                        // should happen, however it seems that csc does not do that
 
3246
                        //
 
3247
                        if (!DoBinaryOperatorPromotion (ec)) {
 
3248
                                left = ltemp;
 
3249
                                right = rtemp;
 
3250
                                return null;
 
3251
                        }
 
3252
 
 
3253
                        if (underlying_type_result != null && left.Type != underlying_type_result) {
 
3254
                                enum_conversion = Convert.ExplicitNumericConversion (ec, new EmptyExpression (left.Type), underlying_type_result);
 
3255
                        }
 
3256
 
 
3257
                        expr = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryStandard, true, res_type);
 
3258
                        if (expr == null)
 
3259
                                return null;
 
3260
 
 
3261
                        if (!IsCompound)
 
3262
                                return expr;
 
3263
 
 
3264
                        //
 
3265
                        // Section: 7.16.2
 
3266
                        //
 
3267
 
 
3268
                        //
 
3269
                        // If the return type of the selected operator is implicitly convertible to the type of x
 
3270
                        //
 
3271
                        if (Convert.ImplicitConversionExists (ec, expr, ltype))
 
3272
                                return expr;
 
3273
 
 
3274
                        //
 
3275
                        // Otherwise, if the selected operator is a predefined operator, if the return type of the
 
3276
                        // selected operator is explicitly convertible to the type of x, and if y is implicitly
 
3277
                        // convertible to the type of x or the operator is a shift operator, then the operation
 
3278
                        // is evaluated as x = (T)(x op y), where T is the type of x
 
3279
                        //
 
3280
                        expr = Convert.ExplicitConversion (ec, expr, ltype, loc);
 
3281
                        if (expr == null)
 
3282
                                return null;
 
3283
 
 
3284
                        if (Convert.ImplicitConversionExists (ec, ltemp, ltype))
 
3285
                                return expr;
 
3286
 
 
3287
                        return null;
 
3288
                }
 
3289
 
 
3290
                //
 
3291
                // 7.9.6 Reference type equality operators
 
3292
                //
 
3293
                Expression ResolveOperatorEquality (ResolveContext ec, TypeSpec l, TypeSpec r)
 
3294
                {
 
3295
                        Expression result;
 
3296
                        type = ec.BuiltinTypes.Bool;
 
3297
 
 
3298
                        //
 
3299
                        // a, Both operands are reference-type values or the value null
 
3300
                        // b, One operand is a value of type T where T is a type-parameter and
 
3301
                        // the other operand is the value null. Furthermore T does not have the
 
3302
                        // value type constraint
 
3303
                        //
 
3304
                        // LAMESPEC: Very confusing details in the specification, basically any
 
3305
                        // reference like type-parameter is allowed
 
3306
                        //
 
3307
                        var tparam_l = l as TypeParameterSpec;
 
3308
                        var tparam_r = r as TypeParameterSpec;
 
3309
                        if (tparam_l != null) {
 
3310
                                if (right is NullLiteral && !tparam_l.HasSpecialStruct) {
 
3311
                                        left = new BoxedCast (left, ec.BuiltinTypes.Object);
 
3312
                                        return this;
 
3313
                                }
 
3314
 
 
3315
                                if (!tparam_l.IsReferenceType)
 
3316
                                        return null;
 
3317
 
 
3318
                                l = tparam_l.GetEffectiveBase ();
 
3319
                                left = new BoxedCast (left, l);
 
3320
                        } else if (left is NullLiteral && tparam_r == null) {
 
3321
                                if (!TypeSpec.IsReferenceType (r) || r.Kind == MemberKind.InternalCompilerType)
 
3322
                                        return null;
 
3323
 
 
3324
                                return this;
 
3325
                        }
 
3326
 
 
3327
                        if (tparam_r != null) {
 
3328
                                if (left is NullLiteral && !tparam_r.HasSpecialStruct) {
 
3329
                                        right = new BoxedCast (right, ec.BuiltinTypes.Object);
 
3330
                                        return this;
 
3331
                                }
 
3332
 
 
3333
                                if (!tparam_r.IsReferenceType)
 
3334
                                        return null;
 
3335
 
 
3336
                                r = tparam_r.GetEffectiveBase ();
 
3337
                                right = new BoxedCast (right, r);
 
3338
                        } else if (right is NullLiteral) {
 
3339
                                if (!TypeSpec.IsReferenceType (l) || l.Kind == MemberKind.InternalCompilerType)
 
3340
                                        return null;
 
3341
 
 
3342
                                return this;
 
3343
                        }
 
3344
 
 
3345
                        //
 
3346
                        // LAMESPEC: method groups can be compared when they convert to other side delegate
 
3347
                        //
 
3348
                        if (l.IsDelegate) {
 
3349
                                if (right.eclass == ExprClass.MethodGroup) {
 
3350
                                        result = Convert.ImplicitConversion (ec, right, l, loc);
 
3351
                                        if (result == null)
 
3352
                                                return null;
 
3353
 
 
3354
                                        right = result;
 
3355
                                        r = l;
 
3356
                                } else if (r.IsDelegate && l != r) {
 
3357
                                        return null;
 
3358
                                }
 
3359
                        } else if (left.eclass == ExprClass.MethodGroup && r.IsDelegate) {
 
3360
                                result = Convert.ImplicitConversionRequired (ec, left, r, loc);
 
3361
                                if (result == null)
 
3362
                                        return null;
 
3363
 
 
3364
                                left = result;
 
3365
                                l = r;
 
3366
                        }
 
3367
 
 
3368
                        //
 
3369
                        // bool operator != (string a, string b)
 
3370
                        // bool operator == (string a, string b)
 
3371
                        //
 
3372
                        // bool operator != (Delegate a, Delegate b)
 
3373
                        // bool operator == (Delegate a, Delegate b)
 
3374
                        //
 
3375
                        // bool operator != (bool a, bool b)
 
3376
                        // bool operator == (bool a, bool b)
 
3377
                        //
 
3378
                        // LAMESPEC: Reference equality comparison can apply to value types when
 
3379
                        // they implement an implicit conversion to any of types above.
 
3380
                        //
 
3381
                        if (r.BuiltinType != BuiltinTypeSpec.Type.Object && l.BuiltinType != BuiltinTypeSpec.Type.Object) {
 
3382
                                result = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryEquality, false, null);
 
3383
                                if (result != null)
 
3384
                                        return result;
 
3385
                        }
 
3386
 
 
3387
                        //
 
3388
                        // bool operator != (object a, object b)
 
3389
                        // bool operator == (object a, object b)
 
3390
                        //
 
3391
                        // An explicit reference conversion exists from the
 
3392
                        // type of either operand to the type of the other operand.
 
3393
                        //
 
3394
 
 
3395
                        // Optimize common path
 
3396
                        if (l == r) {
 
3397
                                return l.Kind == MemberKind.InternalCompilerType || l.Kind == MemberKind.Struct ? null : this;
 
3398
                        }
 
3399
 
 
3400
                        if (!Convert.ExplicitReferenceConversionExists (l, r) &&
 
3401
                                !Convert.ExplicitReferenceConversionExists (r, l))
 
3402
                                return null;
 
3403
 
 
3404
                        // Reject allowed explicit conversions like int->object
 
3405
                        if (!TypeSpec.IsReferenceType (l) || !TypeSpec.IsReferenceType (r))
 
3406
                                return null;
 
3407
 
 
3408
                        if (l.BuiltinType == BuiltinTypeSpec.Type.String || l.BuiltinType == BuiltinTypeSpec.Type.Delegate || MemberCache.GetUserOperator (l, CSharp.Operator.OpType.Equality, false) != null)
 
3409
                                ec.Report.Warning (253, 2, loc,
 
3410
                                        "Possible unintended reference comparison. Consider casting the right side expression to type `{0}' to get value comparison",
 
3411
                                        l.GetSignatureForError ());
 
3412
 
 
3413
                        if (r.BuiltinType == BuiltinTypeSpec.Type.String || r.BuiltinType == BuiltinTypeSpec.Type.Delegate || MemberCache.GetUserOperator (r, CSharp.Operator.OpType.Equality, false) != null)
 
3414
                                ec.Report.Warning (252, 2, loc,
 
3415
                                        "Possible unintended reference comparison. Consider casting the left side expression to type `{0}' to get value comparison",
 
3416
                                        r.GetSignatureForError ());
 
3417
 
 
3418
                        return this;
 
3419
                }
 
3420
 
 
3421
 
 
3422
                Expression ResolveOperatorPointer (ResolveContext ec, TypeSpec l, TypeSpec r)
 
3423
                {
 
3424
                        //
 
3425
                        // bool operator == (void* x, void* y);
 
3426
                        // bool operator != (void* x, void* y);
 
3427
                        // bool operator < (void* x, void* y);
 
3428
                        // bool operator > (void* x, void* y);
 
3429
                        // bool operator <= (void* x, void* y);
 
3430
                        // bool operator >= (void* x, void* y);
 
3431
                        //
 
3432
                        if ((oper & Operator.ComparisonMask) != 0) {
 
3433
                                Expression temp;
 
3434
                                if (!l.IsPointer) {
 
3435
                                        temp = Convert.ImplicitConversion (ec, left, r, left.Location);
 
3436
                                        if (temp == null)
 
3437
                                                return null;
 
3438
                                        left = temp;
 
3439
                                }
 
3440
 
 
3441
                                if (!r.IsPointer) {
 
3442
                                        temp = Convert.ImplicitConversion (ec, right, l, right.Location);
 
3443
                                        if (temp == null)
 
3444
                                                return null;
 
3445
                                        right = temp;
 
3446
                                }
 
3447
 
 
3448
                                type = ec.BuiltinTypes.Bool;
 
3449
                                return this;
 
3450
                        }
 
3451
 
 
3452
                        return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryUnsafe, false, null);
 
3453
                }
 
3454
 
 
3455
                //
 
3456
                // Build-in operators method overloading
 
3457
                //
 
3458
                protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type)
 
3459
                {
 
3460
                        PredefinedOperator best_operator = null;
 
3461
                        TypeSpec l = left.Type;
 
3462
                        TypeSpec r = right.Type;
 
3463
                        Operator oper_mask = oper & ~Operator.ValuesOnlyMask;
 
3464
 
 
3465
                        foreach (PredefinedOperator po in operators) {
 
3466
                                if ((po.OperatorsMask & oper_mask) == 0)
 
3467
                                        continue;
 
3468
 
 
3469
                                if (primitives_only) {
 
3470
                                        if (!po.IsPrimitiveApplicable (l, r))
 
3471
                                                continue;
 
3472
                                } else {
 
3473
                                        if (!po.IsApplicable (ec, left, right))
 
3474
                                                continue;
 
3475
                                }
 
3476
 
 
3477
                                if (best_operator == null) {
 
3478
                                        best_operator = po;
 
3479
                                        if (primitives_only)
 
3480
                                                break;
 
3481
 
 
3482
                                        continue;
 
3483
                                }
 
3484
 
 
3485
                                best_operator = po.ResolveBetterOperator (ec, best_operator);
 
3486
 
 
3487
                                if (best_operator == null) {
 
3488
                                        ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
 
3489
                                                OperName (oper), TypeManager.CSharpName (l), TypeManager.CSharpName (r));
 
3490
 
 
3491
                                        best_operator = po;
 
3492
                                        break;
 
3493
                                }
 
3494
                        }
 
3495
 
 
3496
                        if (best_operator == null)
 
3497
                                return null;
 
3498
 
 
3499
                        Expression expr = best_operator.ConvertResult (ec, this);
 
3500
 
 
3501
                        //
 
3502
                        // Optimize &/&& constant expressions with 0 value
 
3503
                        //
 
3504
                        if (oper == Operator.BitwiseAnd || oper == Operator.LogicalAnd) {
 
3505
                                Constant rc = right as Constant;
 
3506
                                Constant lc = left as Constant;
 
3507
                                if (((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue)) && !(this is Nullable.LiftedBinaryOperator)) {
 
3508
                                        //
 
3509
                                        // The result is a constant with side-effect
 
3510
                                        //
 
3511
                                        Constant side_effect = rc == null ?
 
3512
                                                new SideEffectConstant (lc, right, loc) :
 
3513
                                                new SideEffectConstant (rc, left, loc);
 
3514
 
 
3515
                                        return ReducedExpression.Create (side_effect, expr);
 
3516
                                }
 
3517
                        }
 
3518
 
 
3519
                        if (enum_type == null)
 
3520
                                return expr;
 
3521
 
 
3522
                        //
 
3523
                        // HACK: required by enum_conversion
 
3524
                        //
 
3525
                        expr.Type = enum_type;
 
3526
                        return EmptyCast.Create (expr, enum_type);
 
3527
                }
 
3528
 
 
3529
                //
 
3530
                // Performs user-operator overloading
 
3531
                //
 
3532
                protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression left, Expression right)
 
3533
                {
 
3534
                        var op = ConvertBinaryToUserOperator (oper);
 
3535
                        var l = left.Type;
 
3536
                        if (l.IsNullableType)
 
3537
                                l = Nullable.NullableInfo.GetUnderlyingType (l);
 
3538
                        var r = right.Type;
 
3539
                        if (r.IsNullableType)
 
3540
                                r = Nullable.NullableInfo.GetUnderlyingType (r);
 
3541
 
 
3542
                        IList<MemberSpec> left_operators = MemberCache.GetUserOperator (l, op, false);
 
3543
                        IList<MemberSpec> right_operators = null;
 
3544
 
 
3545
                        if (l != r) {
 
3546
                                right_operators = MemberCache.GetUserOperator (r, op, false);
 
3547
                                if (right_operators == null && left_operators == null)
 
3548
                                        return null;
 
3549
                        } else if (left_operators == null) {
 
3550
                                return null;
 
3551
                        }
 
3552
 
 
3553
                        Arguments args = new Arguments (2);
 
3554
                        Argument larg = new Argument (left);
 
3555
                        args.Add (larg);
 
3556
                        Argument rarg = new Argument (right);
 
3557
                        args.Add (rarg);
 
3558
 
 
3559
                        //
 
3560
                        // User-defined operator implementations always take precedence
 
3561
                        // over predefined operator implementations
 
3562
                        //
 
3563
                        if (left_operators != null && right_operators != null) {
 
3564
                                left_operators = CombineUserOperators (left_operators, right_operators);
 
3565
                        } else if (right_operators != null) {
 
3566
                                left_operators = right_operators;
 
3567
                        }
 
3568
 
 
3569
                        var res = new OverloadResolver (left_operators, OverloadResolver.Restrictions.ProbingOnly | 
 
3570
                                OverloadResolver.Restrictions.NoBaseMembers | OverloadResolver.Restrictions.BaseMembersIncluded, loc);
 
3571
 
 
3572
                        var oper_method = res.ResolveOperator (ec, ref args);
 
3573
                        if (oper_method == null)
 
3574
                                return null;
 
3575
 
 
3576
                        var llifted = (state & State.LeftNullLifted) != 0;
 
3577
                        var rlifted = (state & State.RightNullLifted) != 0;
 
3578
                        if ((Oper & Operator.EqualityMask) != 0) {
 
3579
                                var parameters = oper_method.Parameters;
 
3580
                                // LAMESPEC: No idea why this is not allowed
 
3581
                                if ((left is Nullable.Unwrap || right is Nullable.Unwrap) && parameters.Types [0] != parameters.Types [1])
 
3582
                                        return null;
 
3583
 
 
3584
                                // Binary operation was lifted but we have found a user operator
 
3585
                                // which requires value-type argument, we downgrade ourself back to
 
3586
                                // binary operation
 
3587
                                // LAMESPEC: The user operator is not called (it cannot be we are passing null to struct)
 
3588
                                // but compilation succeeds
 
3589
                                if ((llifted && !parameters.Types[0].IsStruct) || (rlifted && !parameters.Types[1].IsStruct)) {
 
3590
                                        state &= ~(State.LeftNullLifted | State.RightNullLifted);
 
3591
                                }
 
3592
                        }
 
3593
 
 
3594
                        Expression oper_expr;
 
3595
 
 
3596
                        // TODO: CreateExpressionTree is allocated every time
 
3597
                        if ((oper & Operator.LogicalMask) != 0) {
 
3598
                                oper_expr = new ConditionalLogicalOperator (oper_method, args, CreateExpressionTree,
 
3599
                                        oper == Operator.LogicalAnd, loc).Resolve (ec);
 
3600
                        } else {
 
3601
                                oper_expr = new UserOperatorCall (oper_method, args, CreateExpressionTree, loc);
 
3602
                        }
 
3603
 
 
3604
                        if (!llifted)
 
3605
                                this.left = larg.Expr;
 
3606
 
 
3607
                        if (!rlifted)
 
3608
                                this.right = rarg.Expr;
 
3609
 
 
3610
                        return oper_expr;
 
3611
                }
 
3612
 
 
3613
                //
 
3614
                // Merge two sets of user operators into one, they are mostly distinguish
 
3615
                // expect when they share base type and it contains an operator
 
3616
                //
 
3617
                static IList<MemberSpec> CombineUserOperators (IList<MemberSpec> left, IList<MemberSpec> right)
 
3618
                {
 
3619
                        var combined = new List<MemberSpec> (left.Count + right.Count);
 
3620
                        combined.AddRange (left);
 
3621
                        foreach (var r in right) {
 
3622
                                bool same = false;
 
3623
                                foreach (var l in left) {
 
3624
                                        if (l.DeclaringType == r.DeclaringType) {
 
3625
                                                same = true;
 
3626
                                                break;
 
3627
                                        }
 
3628
                                }
 
3629
 
 
3630
                                if (!same)
 
3631
                                        combined.Add (r);
 
3632
                        }
 
3633
 
 
3634
                        return combined;
 
3635
                }
 
3636
 
 
3637
                void CheckOutOfRangeComparison (ResolveContext ec, Constant c, TypeSpec type)
 
3638
                {
 
3639
                        if (c is IntegralConstant || c is CharConstant) {
 
3640
                                try {
 
3641
                                        c.ConvertExplicitly (true, type);
 
3642
                                } catch (OverflowException) {
 
3643
                                        ec.Report.Warning (652, 2, loc,
 
3644
                                                "A comparison between a constant and a variable is useless. The constant is out of the range of the variable type `{0}'",
 
3645
                                                TypeManager.CSharpName (type));
 
3646
                                }
 
3647
                        }
 
3648
                }
 
3649
 
 
3650
                /// <remarks>
 
3651
                ///   EmitBranchable is called from Statement.EmitBoolExpression in the
 
3652
                ///   context of a conditional bool expression.  This function will return
 
3653
                ///   false if it is was possible to use EmitBranchable, or true if it was.
 
3654
                ///
 
3655
                ///   The expression's code is generated, and we will generate a branch to `target'
 
3656
                ///   if the resulting expression value is equal to isTrue
 
3657
                /// </remarks>
 
3658
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 
3659
                {
 
3660
                        //
 
3661
                        // This is more complicated than it looks, but its just to avoid
 
3662
                        // duplicated tests: basically, we allow ==, !=, >, <, >= and <=
 
3663
                        // but on top of that we want for == and != to use a special path
 
3664
                        // if we are comparing against null
 
3665
                        //
 
3666
                        if ((oper & Operator.EqualityMask) != 0 && (left is Constant || right is Constant)) {
 
3667
                                bool my_on_true = oper == Operator.Inequality ? on_true : !on_true;
 
3668
                                
 
3669
                                //
 
3670
                                // put the constant on the rhs, for simplicity
 
3671
                                //
 
3672
                                if (left is Constant) {
 
3673
                                        Expression swap = right;
 
3674
                                        right = left;
 
3675
                                        left = swap;
 
3676
                                }
 
3677
                                
 
3678
                                //
 
3679
                                // brtrue/brfalse works with native int only
 
3680
                                //
 
3681
                                if (((Constant) right).IsZeroInteger && right.Type.BuiltinType != BuiltinTypeSpec.Type.Long && right.Type.BuiltinType != BuiltinTypeSpec.Type.ULong) {
 
3682
                                        left.EmitBranchable (ec, target, my_on_true);
 
3683
                                        return;
 
3684
                                }
 
3685
                                if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) {
 
3686
                                        // right is a boolean, and it's not 'false' => it is 'true'
 
3687
                                        left.EmitBranchable (ec, target, !my_on_true);
 
3688
                                        return;
 
3689
                                }
 
3690
 
 
3691
                        } else if (oper == Operator.LogicalAnd) {
 
3692
 
 
3693
                                if (on_true) {
 
3694
                                        Label tests_end = ec.DefineLabel ();
 
3695
                                        
 
3696
                                        left.EmitBranchable (ec, tests_end, false);
 
3697
                                        right.EmitBranchable (ec, target, true);
 
3698
                                        ec.MarkLabel (tests_end);                                       
 
3699
                                } else {
 
3700
                                        //
 
3701
                                        // This optimizes code like this 
 
3702
                                        // if (true && i > 4)
 
3703
                                        //
 
3704
                                        if (!(left is Constant))
 
3705
                                                left.EmitBranchable (ec, target, false);
 
3706
 
 
3707
                                        if (!(right is Constant)) 
 
3708
                                                right.EmitBranchable (ec, target, false);
 
3709
                                }
 
3710
                                
 
3711
                                return;
 
3712
                                
 
3713
                        } else if (oper == Operator.LogicalOr){
 
3714
                                if (on_true) {
 
3715
                                        left.EmitBranchable (ec, target, true);
 
3716
                                        right.EmitBranchable (ec, target, true);
 
3717
                                        
 
3718
                                } else {
 
3719
                                        Label tests_end = ec.DefineLabel ();
 
3720
                                        left.EmitBranchable (ec, tests_end, true);
 
3721
                                        right.EmitBranchable (ec, target, false);
 
3722
                                        ec.MarkLabel (tests_end);
 
3723
                                }
 
3724
                                
 
3725
                                return;
 
3726
 
 
3727
                        } else if ((oper & Operator.ComparisonMask) == 0) {
 
3728
                                base.EmitBranchable (ec, target, on_true);
 
3729
                                return;
 
3730
                        }
 
3731
                        
 
3732
                        left.Emit (ec);
 
3733
                        right.Emit (ec);
 
3734
 
 
3735
                        TypeSpec t = left.Type;
 
3736
                        bool is_float = IsFloat (t);
 
3737
                        bool is_unsigned = is_float || IsUnsigned (t);
 
3738
                        
 
3739
                        switch (oper){
 
3740
                        case Operator.Equality:
 
3741
                                if (on_true)
 
3742
                                        ec.Emit (OpCodes.Beq, target);
 
3743
                                else
 
3744
                                        ec.Emit (OpCodes.Bne_Un, target);
 
3745
                                break;
 
3746
 
 
3747
                        case Operator.Inequality:
 
3748
                                if (on_true)
 
3749
                                        ec.Emit (OpCodes.Bne_Un, target);
 
3750
                                else
 
3751
                                        ec.Emit (OpCodes.Beq, target);
 
3752
                                break;
 
3753
 
 
3754
                        case Operator.LessThan:
 
3755
                                if (on_true)
 
3756
                                        if (is_unsigned && !is_float)
 
3757
                                                ec.Emit (OpCodes.Blt_Un, target);
 
3758
                                        else
 
3759
                                                ec.Emit (OpCodes.Blt, target);
 
3760
                                else
 
3761
                                        if (is_unsigned)
 
3762
                                                ec.Emit (OpCodes.Bge_Un, target);
 
3763
                                        else
 
3764
                                                ec.Emit (OpCodes.Bge, target);
 
3765
                                break;
 
3766
 
 
3767
                        case Operator.GreaterThan:
 
3768
                                if (on_true)
 
3769
                                        if (is_unsigned && !is_float)
 
3770
                                                ec.Emit (OpCodes.Bgt_Un, target);
 
3771
                                        else
 
3772
                                                ec.Emit (OpCodes.Bgt, target);
 
3773
                                else
 
3774
                                        if (is_unsigned)
 
3775
                                                ec.Emit (OpCodes.Ble_Un, target);
 
3776
                                        else
 
3777
                                                ec.Emit (OpCodes.Ble, target);
 
3778
                                break;
 
3779
 
 
3780
                        case Operator.LessThanOrEqual:
 
3781
                                if (on_true)
 
3782
                                        if (is_unsigned && !is_float)
 
3783
                                                ec.Emit (OpCodes.Ble_Un, target);
 
3784
                                        else
 
3785
                                                ec.Emit (OpCodes.Ble, target);
 
3786
                                else
 
3787
                                        if (is_unsigned)
 
3788
                                                ec.Emit (OpCodes.Bgt_Un, target);
 
3789
                                        else
 
3790
                                                ec.Emit (OpCodes.Bgt, target);
 
3791
                                break;
 
3792
 
 
3793
 
 
3794
                        case Operator.GreaterThanOrEqual:
 
3795
                                if (on_true)
 
3796
                                        if (is_unsigned && !is_float)
 
3797
                                                ec.Emit (OpCodes.Bge_Un, target);
 
3798
                                        else
 
3799
                                                ec.Emit (OpCodes.Bge, target);
 
3800
                                else
 
3801
                                        if (is_unsigned)
 
3802
                                                ec.Emit (OpCodes.Blt_Un, target);
 
3803
                                        else
 
3804
                                                ec.Emit (OpCodes.Blt, target);
 
3805
                                break;
 
3806
                        default:
 
3807
                                throw new InternalErrorException (oper.ToString ());
 
3808
                        }
 
3809
                }
 
3810
                
 
3811
                public override void Emit (EmitContext ec)
 
3812
                {
 
3813
                        EmitOperator (ec, left.Type);
 
3814
                }
 
3815
 
 
3816
                protected virtual void EmitOperator (EmitContext ec, TypeSpec l)
 
3817
                {
 
3818
                        //
 
3819
                        // Handle short-circuit operators differently
 
3820
                        // than the rest
 
3821
                        //
 
3822
                        if ((oper & Operator.LogicalMask) != 0) {
 
3823
                                Label load_result = ec.DefineLabel ();
 
3824
                                Label end = ec.DefineLabel ();
 
3825
 
 
3826
                                bool is_or = oper == Operator.LogicalOr;
 
3827
                                left.EmitBranchable (ec, load_result, is_or);
 
3828
                                right.Emit (ec);
 
3829
                                ec.Emit (OpCodes.Br_S, end);
 
3830
                                
 
3831
                                ec.MarkLabel (load_result);
 
3832
                                ec.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
 
3833
                                ec.MarkLabel (end);
 
3834
                                return;
 
3835
                        }
 
3836
 
 
3837
                        //
 
3838
                        // Optimize zero-based operations which cannot be optimized at expression level
 
3839
                        //
 
3840
                        if (oper == Operator.Subtraction) {
 
3841
                                var lc = left as IntegralConstant;
 
3842
                                if (lc != null && lc.IsDefaultValue) {
 
3843
                                        right.Emit (ec);
 
3844
                                        ec.Emit (OpCodes.Neg);
 
3845
                                        return;
 
3846
                                }
 
3847
                        }
 
3848
 
 
3849
                        left.Emit (ec);
 
3850
                        right.Emit (ec);
 
3851
                        EmitOperatorOpcode (ec, oper, l);
 
3852
 
 
3853
                        //
 
3854
                        // Nullable enum could require underlying type cast and we cannot simply wrap binary
 
3855
                        // expression because that would wrap lifted binary operation
 
3856
                        //
 
3857
                        if (enum_conversion != null)
 
3858
                                enum_conversion.Emit (ec);
 
3859
                }
 
3860
 
 
3861
                public override void EmitSideEffect (EmitContext ec)
 
3862
                {
 
3863
                        if ((oper & Operator.LogicalMask) != 0 ||
 
3864
                                (ec.HasSet (EmitContext.Options.CheckedScope) && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) {
 
3865
                                base.EmitSideEffect (ec);
 
3866
                        } else {
 
3867
                                left.EmitSideEffect (ec);
 
3868
                                right.EmitSideEffect (ec);
 
3869
                        }
 
3870
                }
 
3871
 
 
3872
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
3873
                {
 
3874
                        Binary target = (Binary) t;
 
3875
 
 
3876
                        target.left = left.Clone (clonectx);
 
3877
                        target.right = right.Clone (clonectx);
 
3878
                }
 
3879
 
 
3880
                public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args)
 
3881
                {
 
3882
                        Arguments binder_args = new Arguments (4);
 
3883
 
 
3884
                        MemberAccess sle = new MemberAccess (new MemberAccess (
 
3885
                                new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc);
 
3886
 
 
3887
                        CSharpBinderFlags flags = 0;
 
3888
                        if (ec.HasSet (ResolveContext.Options.CheckedScope))
 
3889
                                flags = CSharpBinderFlags.CheckedContext;
 
3890
 
 
3891
                        if ((oper & Operator.LogicalMask) != 0)
 
3892
                                flags |= CSharpBinderFlags.BinaryOperationLogical;
 
3893
 
 
3894
                        binder_args.Add (new Argument (new EnumConstant (new IntLiteral (ec.BuiltinTypes, (int) flags, loc), ec.Module.PredefinedTypes.BinderFlags.Resolve ())));
 
3895
                        binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc)));
 
3896
                        binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc)));                                                                      
 
3897
                        binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc)));
 
3898
 
 
3899
                        return new Invocation (new MemberAccess (new TypeExpression (ec.Module.PredefinedTypes.Binder.TypeSpec, loc), "BinaryOperation", loc), binder_args);
 
3900
                }
 
3901
                
 
3902
                public override Expression CreateExpressionTree (ResolveContext ec)
 
3903
                {
 
3904
                        return CreateExpressionTree (ec, null);
 
3905
                }
 
3906
 
 
3907
                Expression CreateExpressionTree (ResolveContext ec, Expression method)          
 
3908
                {
 
3909
                        string method_name;
 
3910
                        bool lift_arg = false;
 
3911
                        
 
3912
                        switch (oper) {
 
3913
                        case Operator.Addition:
 
3914
                                if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type))
 
3915
                                        method_name = "AddChecked";
 
3916
                                else
 
3917
                                        method_name = "Add";
 
3918
                                break;
 
3919
                        case Operator.BitwiseAnd:
 
3920
                                method_name = "And";
 
3921
                                break;
 
3922
                        case Operator.BitwiseOr:
 
3923
                                method_name = "Or";
 
3924
                                break;
 
3925
                        case Operator.Division:
 
3926
                                method_name = "Divide";
 
3927
                                break;
 
3928
                        case Operator.Equality:
 
3929
                                method_name = "Equal";
 
3930
                                lift_arg = true;
 
3931
                                break;
 
3932
                        case Operator.ExclusiveOr:
 
3933
                                method_name = "ExclusiveOr";
 
3934
                                break;                          
 
3935
                        case Operator.GreaterThan:
 
3936
                                method_name = "GreaterThan";
 
3937
                                lift_arg = true;
 
3938
                                break;
 
3939
                        case Operator.GreaterThanOrEqual:
 
3940
                                method_name = "GreaterThanOrEqual";
 
3941
                                lift_arg = true;
 
3942
                                break;
 
3943
                        case Operator.Inequality:
 
3944
                                method_name = "NotEqual";
 
3945
                                lift_arg = true;
 
3946
                                break;
 
3947
                        case Operator.LeftShift:
 
3948
                                method_name = "LeftShift";
 
3949
                                break;
 
3950
                        case Operator.LessThan:
 
3951
                                method_name = "LessThan";
 
3952
                                lift_arg = true;
 
3953
                                break;
 
3954
                        case Operator.LessThanOrEqual:
 
3955
                                method_name = "LessThanOrEqual";
 
3956
                                lift_arg = true;
 
3957
                                break;
 
3958
                        case Operator.LogicalAnd:
 
3959
                                method_name = "AndAlso";
 
3960
                                break;
 
3961
                        case Operator.LogicalOr:
 
3962
                                method_name = "OrElse";
 
3963
                                break;
 
3964
                        case Operator.Modulus:
 
3965
                                method_name = "Modulo";
 
3966
                                break;
 
3967
                        case Operator.Multiply:
 
3968
                                if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type))
 
3969
                                        method_name = "MultiplyChecked";
 
3970
                                else
 
3971
                                        method_name = "Multiply";
 
3972
                                break;
 
3973
                        case Operator.RightShift:
 
3974
                                method_name = "RightShift";
 
3975
                                break;
 
3976
                        case Operator.Subtraction:
 
3977
                                if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type))
 
3978
                                        method_name = "SubtractChecked";
 
3979
                                else
 
3980
                                        method_name = "Subtract";
 
3981
                                break;
 
3982
 
 
3983
                        default:
 
3984
                                throw new InternalErrorException ("Unknown expression tree binary operator " + oper);
 
3985
                        }
 
3986
 
 
3987
                        Arguments args = new Arguments (2);
 
3988
                        args.Add (new Argument (left.CreateExpressionTree (ec)));
 
3989
                        args.Add (new Argument (right.CreateExpressionTree (ec)));
 
3990
                        if (method != null) {
 
3991
                                if (lift_arg)
 
3992
                                        args.Add (new Argument (new BoolLiteral (ec.BuiltinTypes, false, loc)));
 
3993
 
 
3994
                                args.Add (new Argument (method));
 
3995
                        }
 
3996
                        
 
3997
                        return CreateExpressionFactoryCall (ec, method_name, args);
 
3998
                }
 
3999
                
 
4000
                public override object Accept (StructuralVisitor visitor)
 
4001
                {
 
4002
                        return visitor.Visit (this);
 
4003
                }
 
4004
 
 
4005
        }
 
4006
        
 
4007
        //
 
4008
        // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
 
4009
        // b, c, d... may be strings or objects.
 
4010
        //
 
4011
        public class StringConcat : Expression
 
4012
        {
 
4013
                Arguments arguments;
 
4014
                
 
4015
                StringConcat (Location loc)
 
4016
                {
 
4017
                        this.loc = loc;
 
4018
                        arguments = new Arguments (2);
 
4019
                }
 
4020
 
 
4021
                public static StringConcat Create (ResolveContext rc, Expression left, Expression right, Location loc)
 
4022
                {
 
4023
                        if (left.eclass == ExprClass.Unresolved || right.eclass == ExprClass.Unresolved)
 
4024
                                throw new ArgumentException ();
 
4025
 
 
4026
                        var s = new StringConcat (loc);
 
4027
                        s.type = rc.BuiltinTypes.String;
 
4028
                        s.eclass = ExprClass.Value;
 
4029
 
 
4030
                        s.Append (rc, left);
 
4031
                        s.Append (rc, right);
 
4032
                        return s;
 
4033
                }
 
4034
 
 
4035
                public override Expression CreateExpressionTree (ResolveContext ec)
 
4036
                {
 
4037
                        Argument arg = arguments [0];
 
4038
                        return CreateExpressionAddCall (ec, arg, arg.CreateExpressionTree (ec), 1);
 
4039
                }
 
4040
 
 
4041
                //
 
4042
                // Creates nested calls tree from an array of arguments used for IL emit
 
4043
                //
 
4044
                Expression CreateExpressionAddCall (ResolveContext ec, Argument left, Expression left_etree, int pos)
 
4045
                {
 
4046
                        Arguments concat_args = new Arguments (2);
 
4047
                        Arguments add_args = new Arguments (3);
 
4048
 
 
4049
                        concat_args.Add (left);
 
4050
                        add_args.Add (new Argument (left_etree));
 
4051
 
 
4052
                        concat_args.Add (arguments [pos]);
 
4053
                        add_args.Add (new Argument (arguments [pos].CreateExpressionTree (ec)));
 
4054
 
 
4055
                        var methods = GetConcatMethodCandidates ();
 
4056
                        if (methods == null)
 
4057
                                return null;
 
4058
 
 
4059
                        var res = new OverloadResolver (methods, OverloadResolver.Restrictions.NoBaseMembers, loc);
 
4060
                        var method = res.ResolveMember<MethodSpec> (ec, ref concat_args);
 
4061
                        if (method == null)
 
4062
                                return null;
 
4063
 
 
4064
                        add_args.Add (new Argument (new TypeOfMethod (method, loc)));
 
4065
 
 
4066
                        Expression expr = CreateExpressionFactoryCall (ec, "Add", add_args);
 
4067
                        if (++pos == arguments.Count)
 
4068
                                return expr;
 
4069
 
 
4070
                        left = new Argument (new EmptyExpression (method.ReturnType));
 
4071
                        return CreateExpressionAddCall (ec, left, expr, pos);
 
4072
                }
 
4073
 
 
4074
                protected override Expression DoResolve (ResolveContext ec)
 
4075
                {
 
4076
                        return this;
 
4077
                }
 
4078
                
 
4079
                void Append (ResolveContext rc, Expression operand)
 
4080
                {
 
4081
                        //
 
4082
                        // Constant folding
 
4083
                        //
 
4084
                        StringConstant sc = operand as StringConstant;
 
4085
                        if (sc != null) {
 
4086
                                if (arguments.Count != 0) {
 
4087
                                        Argument last_argument = arguments [arguments.Count - 1];
 
4088
                                        StringConstant last_expr_constant = last_argument.Expr as StringConstant;
 
4089
                                        if (last_expr_constant != null) {
 
4090
                                                last_argument.Expr = new StringConstant (rc.BuiltinTypes, last_expr_constant.Value + sc.Value, sc.Location);
 
4091
                                                return;
 
4092
                                        }
 
4093
                                }
 
4094
                        } else {
 
4095
                                //
 
4096
                                // Multiple (3+) concatenation are resolved as multiple StringConcat instances
 
4097
                                //
 
4098
                                StringConcat concat_oper = operand as StringConcat;
 
4099
                                if (concat_oper != null) {
 
4100
                                        arguments.AddRange (concat_oper.arguments);
 
4101
                                        return;
 
4102
                                }
 
4103
                        }
 
4104
 
 
4105
                        arguments.Add (new Argument (operand));
 
4106
                }
 
4107
 
 
4108
                IList<MemberSpec> GetConcatMethodCandidates ()
 
4109
                {
 
4110
                        return MemberCache.FindMembers (type, "Concat", true);
 
4111
                }
 
4112
 
 
4113
                public override void Emit (EmitContext ec)
 
4114
                {
 
4115
                        var members = GetConcatMethodCandidates ();
 
4116
                        var res = new OverloadResolver (members, OverloadResolver.Restrictions.NoBaseMembers, loc);
 
4117
                        var method = res.ResolveMember<MethodSpec> (new ResolveContext (ec.MemberContext), ref arguments);
 
4118
                        if (method != null)
 
4119
                                Invocation.EmitCall (ec, null, method, arguments, loc);
 
4120
                }
 
4121
 
 
4122
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
4123
                {
 
4124
                        if (arguments.Count != 2)
 
4125
                                throw new NotImplementedException ("arguments.Count != 2");
 
4126
 
 
4127
                        var concat = typeof (string).GetMethod ("Concat", new[] { typeof (object), typeof (object) });
 
4128
                        return SLE.Expression.Add (arguments[0].Expr.MakeExpression (ctx), arguments[1].Expr.MakeExpression (ctx), concat);
 
4129
                }
 
4130
        }
 
4131
 
 
4132
        //
 
4133
        // User-defined conditional logical operator
 
4134
        //
 
4135
        public class ConditionalLogicalOperator : UserOperatorCall {
 
4136
                readonly bool is_and;
 
4137
                Expression oper_expr;
 
4138
 
 
4139
                public ConditionalLogicalOperator (MethodSpec oper, Arguments arguments, Func<ResolveContext, Expression, Expression> expr_tree, bool is_and, Location loc)
 
4140
                        : base (oper, arguments, expr_tree, loc)
 
4141
                {
 
4142
                        this.is_and = is_and;
 
4143
                        eclass = ExprClass.Unresolved;
 
4144
                }
 
4145
                
 
4146
                protected override Expression DoResolve (ResolveContext ec)
 
4147
                {
 
4148
                        AParametersCollection pd = oper.Parameters;
 
4149
                        if (!TypeSpecComparer.IsEqual (type, pd.Types[0]) || !TypeSpecComparer.IsEqual (type, pd.Types[1])) {
 
4150
                                ec.Report.Error (217, loc,
 
4151
                                        "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator",
 
4152
                                        oper.GetSignatureForError ());
 
4153
                                return null;
 
4154
                        }
 
4155
 
 
4156
                        Expression left_dup = new EmptyExpression (type);
 
4157
                        Expression op_true = GetOperatorTrue (ec, left_dup, loc);
 
4158
                        Expression op_false = GetOperatorFalse (ec, left_dup, loc);
 
4159
                        if (op_true == null || op_false == null) {
 
4160
                                ec.Report.Error (218, loc,
 
4161
                                        "The type `{0}' must have operator `true' and operator `false' defined when `{1}' is used as a short circuit operator",
 
4162
                                        TypeManager.CSharpName (type), oper.GetSignatureForError ());
 
4163
                                return null;
 
4164
                        }
 
4165
 
 
4166
                        oper_expr = is_and ? op_false : op_true;
 
4167
                        eclass = ExprClass.Value;
 
4168
                        return this;
 
4169
                }
 
4170
 
 
4171
                public override void Emit (EmitContext ec)
 
4172
                {
 
4173
                        Label end_target = ec.DefineLabel ();
 
4174
 
 
4175
                        //
 
4176
                        // Emit and duplicate left argument
 
4177
                        //
 
4178
                        arguments [0].Expr.Emit (ec);
 
4179
                        ec.Emit (OpCodes.Dup);
 
4180
                        arguments.RemoveAt (0);
 
4181
 
 
4182
                        oper_expr.EmitBranchable (ec, end_target, true);
 
4183
                        base.Emit (ec);
 
4184
                        ec.MarkLabel (end_target);
 
4185
                }
 
4186
        }
 
4187
 
 
4188
        public class PointerArithmetic : Expression {
 
4189
                Expression left, right;
 
4190
                Binary.Operator op;
 
4191
 
 
4192
                //
 
4193
                // We assume that `l' is always a pointer
 
4194
                //
 
4195
                public PointerArithmetic (Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc)
 
4196
                {
 
4197
                        type = t;
 
4198
                        this.loc = loc;
 
4199
                        left = l;
 
4200
                        right = r;
 
4201
                        this.op = op;
 
4202
                }
 
4203
 
 
4204
                public override Expression CreateExpressionTree (ResolveContext ec)
 
4205
                {
 
4206
                        Error_PointerInsideExpressionTree (ec);
 
4207
                        return null;
 
4208
                }
 
4209
 
 
4210
                protected override Expression DoResolve (ResolveContext ec)
 
4211
                {
 
4212
                        eclass = ExprClass.Variable;
 
4213
 
 
4214
                        var pc = left.Type as PointerContainer;
 
4215
                        if (pc != null && pc.Element.Kind == MemberKind.Void) {
 
4216
                                Error_VoidPointerOperation (ec);
 
4217
                                return null;
 
4218
                        }
 
4219
                        
 
4220
                        return this;
 
4221
                }
 
4222
 
 
4223
                public override void Emit (EmitContext ec)
 
4224
                {
 
4225
                        TypeSpec op_type = left.Type;
 
4226
                        
 
4227
                        // It must be either array or fixed buffer
 
4228
                        TypeSpec element;
 
4229
                        if (TypeManager.HasElementType (op_type)) {
 
4230
                                element = TypeManager.GetElementType (op_type);
 
4231
                        } else {
 
4232
                                FieldExpr fe = left as FieldExpr;
 
4233
                                if (fe != null)
 
4234
                                        element = ((FixedFieldSpec) (fe.Spec)).ElementType;
 
4235
                                else
 
4236
                                        element = op_type;
 
4237
                        }
 
4238
 
 
4239
                        int size = BuiltinTypeSpec.GetSize(element);
 
4240
                        TypeSpec rtype = right.Type;
 
4241
                        
 
4242
                        if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){
 
4243
                                //
 
4244
                                // handle (pointer - pointer)
 
4245
                                //
 
4246
                                left.Emit (ec);
 
4247
                                right.Emit (ec);
 
4248
                                ec.Emit (OpCodes.Sub);
 
4249
 
 
4250
                                if (size != 1){
 
4251
                                        if (size == 0)
 
4252
                                                ec.Emit (OpCodes.Sizeof, element);
 
4253
                                        else 
 
4254
                                                ec.EmitInt (size);
 
4255
                                        ec.Emit (OpCodes.Div);
 
4256
                                }
 
4257
                                ec.Emit (OpCodes.Conv_I8);
 
4258
                        } else {
 
4259
                                //
 
4260
                                // handle + and - on (pointer op int)
 
4261
                                //
 
4262
                                Constant left_const = left as Constant;
 
4263
                                if (left_const != null) {
 
4264
                                        //
 
4265
                                        // Optimize ((T*)null) pointer operations
 
4266
                                        //
 
4267
                                        if (left_const.IsDefaultValue) {
 
4268
                                                left = EmptyExpression.Null;
 
4269
                                        } else {
 
4270
                                                left_const = null;
 
4271
                                        }
 
4272
                                }
 
4273
 
 
4274
                                left.Emit (ec);
 
4275
 
 
4276
                                var right_const = right as Constant;
 
4277
                                if (right_const != null) {
 
4278
                                        //
 
4279
                                        // Optimize 0-based arithmetic
 
4280
                                        //
 
4281
                                        if (right_const.IsDefaultValue)
 
4282
                                                return;
 
4283
 
 
4284
                                        if (size != 0)
 
4285
                                                right = new IntConstant (ec.BuiltinTypes, size, right.Location);
 
4286
                                        else
 
4287
                                                right = new SizeOf (new TypeExpression (element, right.Location), right.Location);
 
4288
                                        
 
4289
                                        // TODO: Should be the checks resolve context sensitive?
 
4290
                                        ResolveContext rc = new ResolveContext (ec.MemberContext, ResolveContext.Options.UnsafeScope);
 
4291
                                        right = new Binary (Binary.Operator.Multiply, right, right_const, loc).Resolve (rc);
 
4292
                                        if (right == null)
 
4293
                                                return;
 
4294
                                }
 
4295
 
 
4296
                                right.Emit (ec);
 
4297
                                switch (rtype.BuiltinType) {
 
4298
                                case BuiltinTypeSpec.Type.SByte:
 
4299
                                case BuiltinTypeSpec.Type.Byte:
 
4300
                                case BuiltinTypeSpec.Type.Short:
 
4301
                                case BuiltinTypeSpec.Type.UShort:
 
4302
                                        ec.Emit (OpCodes.Conv_I);
 
4303
                                        break;
 
4304
                                case BuiltinTypeSpec.Type.UInt:
 
4305
                                        ec.Emit (OpCodes.Conv_U);
 
4306
                                        break;
 
4307
                                }
 
4308
 
 
4309
                                if (right_const == null && size != 1){
 
4310
                                        if (size == 0)
 
4311
                                                ec.Emit (OpCodes.Sizeof, element);
 
4312
                                        else 
 
4313
                                                ec.EmitInt (size);
 
4314
                                        if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long || rtype.BuiltinType == BuiltinTypeSpec.Type.ULong)
 
4315
                                                ec.Emit (OpCodes.Conv_I8);
 
4316
 
 
4317
                                        Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype);
 
4318
                                }
 
4319
 
 
4320
                                if (left_const == null) {
 
4321
                                        if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long)
 
4322
                                                ec.Emit (OpCodes.Conv_I);
 
4323
                                        else if (rtype.BuiltinType == BuiltinTypeSpec.Type.ULong)
 
4324
                                                ec.Emit (OpCodes.Conv_U);
 
4325
 
 
4326
                                        Binary.EmitOperatorOpcode (ec, op, op_type);
 
4327
                                }
 
4328
                        }
 
4329
                }
 
4330
        }
 
4331
 
 
4332
        //
 
4333
        // A boolean-expression is an expression that yields a result
 
4334
        // of type bool
 
4335
        //
 
4336
        public class BooleanExpression : ShimExpression
 
4337
        {
 
4338
                public BooleanExpression (Expression expr)
 
4339
                        : base (expr)
 
4340
                {
 
4341
                        this.loc = expr.Location;
 
4342
                }
 
4343
 
 
4344
                public override Expression CreateExpressionTree (ResolveContext ec)
 
4345
                {
 
4346
                        // TODO: We should emit IsTrue (v4) instead of direct user operator
 
4347
                        // call but that would break csc compatibility
 
4348
                        return base.CreateExpressionTree (ec);
 
4349
                }
 
4350
 
 
4351
                protected override Expression DoResolve (ResolveContext ec)
 
4352
                {
 
4353
                        // A boolean-expression is required to be of a type
 
4354
                        // that can be implicitly converted to bool or of
 
4355
                        // a type that implements operator true
 
4356
 
 
4357
                        expr = expr.Resolve (ec);
 
4358
                        if (expr == null)
 
4359
                                return null;
 
4360
 
 
4361
                        Assign ass = expr as Assign;
 
4362
                        if (ass != null && ass.Source is Constant) {
 
4363
                                ec.Report.Warning (665, 3, loc,
 
4364
                                        "Assignment in conditional expression is always constant. Did you mean to use `==' instead ?");
 
4365
                        }
 
4366
 
 
4367
                        if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Bool)
 
4368
                                return expr;
 
4369
 
 
4370
                        if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
4371
                                Arguments args = new Arguments (1);
 
4372
                                args.Add (new Argument (expr));
 
4373
                                return DynamicUnaryConversion.CreateIsTrue (ec, args, loc).Resolve (ec);
 
4374
                        }
 
4375
 
 
4376
                        type = ec.BuiltinTypes.Bool;
 
4377
                        Expression converted = Convert.ImplicitConversion (ec, expr, type, loc);
 
4378
                        if (converted != null)
 
4379
                                return converted;
 
4380
 
 
4381
                        //
 
4382
                        // If no implicit conversion to bool exists, try using `operator true'
 
4383
                        //
 
4384
                        converted = GetOperatorTrue (ec, expr, loc);
 
4385
                        if (converted == null) {
 
4386
                                expr.Error_ValueCannotBeConverted (ec, loc, type, false);
 
4387
                                return null;
 
4388
                        }
 
4389
 
 
4390
                        return converted;
 
4391
                }
 
4392
                
 
4393
                public override object Accept (StructuralVisitor visitor)
 
4394
                {
 
4395
                        return visitor.Visit (this);
 
4396
                }
 
4397
        }
 
4398
 
 
4399
        public class BooleanExpressionFalse : Unary
 
4400
        {
 
4401
                public BooleanExpressionFalse (Expression expr)
 
4402
                        : base (Operator.LogicalNot, expr, expr.Location)
 
4403
                {
 
4404
                }
 
4405
 
 
4406
                protected override Expression ResolveOperator (ResolveContext ec, Expression expr)
 
4407
                {
 
4408
                        return GetOperatorFalse (ec, expr, loc) ?? base.ResolveOperator (ec, expr);
 
4409
                }
 
4410
        }
 
4411
        
 
4412
        /// <summary>
 
4413
        ///   Implements the ternary conditional operator (?:)
 
4414
        /// </summary>
 
4415
        public class Conditional : Expression {
 
4416
                Expression expr, true_expr, false_expr;
 
4417
 
 
4418
                public Conditional (Expression expr, Expression true_expr, Expression false_expr, Location loc)
 
4419
                {
 
4420
                        this.expr = expr;
 
4421
                        this.true_expr = true_expr;
 
4422
                        this.false_expr = false_expr;
 
4423
                        this.loc = loc;
 
4424
                }
 
4425
 
 
4426
                public Expression Expr {
 
4427
                        get {
 
4428
                                return expr;
 
4429
                        }
 
4430
                }
 
4431
 
 
4432
                public Expression TrueExpr {
 
4433
                        get {
 
4434
                                return true_expr;
 
4435
                        }
 
4436
                }
 
4437
 
 
4438
                public Expression FalseExpr {
 
4439
                        get {
 
4440
                                return false_expr;
 
4441
                        }
 
4442
                }
 
4443
                
 
4444
                public override Expression CreateExpressionTree (ResolveContext ec)
 
4445
                {
 
4446
                        Arguments args = new Arguments (3);
 
4447
                        args.Add (new Argument (expr.CreateExpressionTree (ec)));
 
4448
                        args.Add (new Argument (true_expr.CreateExpressionTree (ec)));
 
4449
                        args.Add (new Argument (false_expr.CreateExpressionTree (ec)));
 
4450
                        return CreateExpressionFactoryCall (ec, "Condition", args);
 
4451
                }
 
4452
 
 
4453
                protected override Expression DoResolve (ResolveContext ec)
 
4454
                {
 
4455
                        expr = expr.Resolve (ec);
 
4456
                        true_expr = true_expr.Resolve (ec);
 
4457
                        false_expr = false_expr.Resolve (ec);
 
4458
 
 
4459
                        if (true_expr == null || false_expr == null || expr == null)
 
4460
                                return null;
 
4461
 
 
4462
                        eclass = ExprClass.Value;
 
4463
                        TypeSpec true_type = true_expr.Type;
 
4464
                        TypeSpec false_type = false_expr.Type;
 
4465
                        type = true_type;
 
4466
 
 
4467
                        //
 
4468
                        // First, if an implicit conversion exists from true_expr
 
4469
                        // to false_expr, then the result type is of type false_expr.Type
 
4470
                        //
 
4471
                        if (!TypeSpecComparer.IsEqual (true_type, false_type)) {
 
4472
                                Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc);
 
4473
                                if (conv != null && true_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic) {
 
4474
                                        //
 
4475
                                        // Check if both can convert implicitly to each other's type
 
4476
                                        //
 
4477
                                        type = false_type;
 
4478
 
 
4479
                                        if (false_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) {
 
4480
                                                ec.Report.Error (172, true_expr.Location,
 
4481
                                                        "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other",
 
4482
                                                                true_type.GetSignatureForError (), false_type.GetSignatureForError ());
 
4483
                                                return null;
 
4484
                                        }
 
4485
 
 
4486
                                        true_expr = conv;
 
4487
                                } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) {
 
4488
                                        false_expr = conv;
 
4489
                                } else {
 
4490
                                        ec.Report.Error (173, true_expr.Location,
 
4491
                                                "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'",
 
4492
                                                TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type));
 
4493
                                        return null;
 
4494
                                }
 
4495
                        }                       
 
4496
 
 
4497
                        // Dead code optimalization
 
4498
                        Constant c = expr as Constant;
 
4499
                        if (c != null){
 
4500
                                bool is_false = c.IsDefaultValue;
 
4501
                                ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected");
 
4502
                                return ReducedExpression.Create (
 
4503
                                        is_false ? false_expr : true_expr, this,
 
4504
                                        false_expr is Constant && true_expr is Constant).Resolve (ec);
 
4505
                        }
 
4506
 
 
4507
                        return this;
 
4508
                }
 
4509
 
 
4510
                public override void Emit (EmitContext ec)
 
4511
                {
 
4512
                        Label false_target = ec.DefineLabel ();
 
4513
                        Label end_target = ec.DefineLabel ();
 
4514
 
 
4515
                        expr.EmitBranchable (ec, false_target, false);
 
4516
                        true_expr.Emit (ec);
 
4517
 
 
4518
                        if (type.IsInterface) {
 
4519
                                LocalBuilder temp = ec.GetTemporaryLocal (type);
 
4520
                                ec.Emit (OpCodes.Stloc, temp);
 
4521
                                ec.Emit (OpCodes.Ldloc, temp);
 
4522
                                ec.FreeTemporaryLocal (temp, type);
 
4523
                        }
 
4524
 
 
4525
                        ec.Emit (OpCodes.Br, end_target);
 
4526
                        ec.MarkLabel (false_target);
 
4527
                        false_expr.Emit (ec);
 
4528
                        ec.MarkLabel (end_target);
 
4529
                }
 
4530
 
 
4531
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
4532
                {
 
4533
                        Conditional target = (Conditional) t;
 
4534
 
 
4535
                        target.expr = expr.Clone (clonectx);
 
4536
                        target.true_expr = true_expr.Clone (clonectx);
 
4537
                        target.false_expr = false_expr.Clone (clonectx);
 
4538
                }
 
4539
                
 
4540
                public override object Accept (StructuralVisitor visitor)
 
4541
                {
 
4542
                        return visitor.Visit (this);
 
4543
                }
 
4544
        }
 
4545
 
 
4546
        public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference {
 
4547
                LocalTemporary temp;
 
4548
 
 
4549
                #region Abstract
 
4550
                public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
 
4551
 
 
4552
                public abstract bool IsLockedByStatement { get; set; }
 
4553
 
 
4554
                public abstract bool IsFixed { get; }
 
4555
                public abstract bool IsRef { get; }
 
4556
                public abstract string Name { get; }
 
4557
                public abstract void SetHasAddressTaken ();
 
4558
 
 
4559
                //
 
4560
                // Variable IL data, it has to be protected to encapsulate hoisted variables
 
4561
                //
 
4562
                protected abstract ILocalVariable Variable { get; }
 
4563
                
 
4564
                //
 
4565
                // Variable flow-analysis data
 
4566
                //
 
4567
                public abstract VariableInfo VariableInfo { get; }
 
4568
                #endregion
 
4569
 
 
4570
                public virtual void AddressOf (EmitContext ec, AddressOp mode)
 
4571
                {
 
4572
                        HoistedVariable hv = GetHoistedVariable (ec);
 
4573
                        if (hv != null) {
 
4574
                                hv.AddressOf (ec, mode);
 
4575
                                return;
 
4576
                        }
 
4577
 
 
4578
                        Variable.EmitAddressOf (ec);
 
4579
                }
 
4580
 
 
4581
                public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
 
4582
                {
 
4583
                        if (IsLockedByStatement) {
 
4584
                                rc.Report.Warning (728, 2, loc,
 
4585
                                        "Possibly incorrect assignment to `{0}' which is the argument to a using or lock statement",
 
4586
                                        Name);
 
4587
                        }
 
4588
 
 
4589
                        return this;
 
4590
                }
 
4591
 
 
4592
                public override void Emit (EmitContext ec)
 
4593
                {
 
4594
                        Emit (ec, false);
 
4595
                }
 
4596
 
 
4597
                public override void EmitSideEffect (EmitContext ec)
 
4598
                {
 
4599
                        // do nothing
 
4600
                }
 
4601
 
 
4602
                //
 
4603
                // This method is used by parameters that are references, that are
 
4604
                // being passed as references:  we only want to pass the pointer (that
 
4605
                // is already stored in the parameter, not the address of the pointer,
 
4606
                // and not the value of the variable).
 
4607
                //
 
4608
                public void EmitLoad (EmitContext ec)
 
4609
                {
 
4610
                        Variable.Emit (ec);
 
4611
                }
 
4612
 
 
4613
                public void Emit (EmitContext ec, bool leave_copy)
 
4614
                {
 
4615
                        HoistedVariable hv = GetHoistedVariable (ec);
 
4616
                        if (hv != null) {
 
4617
                                hv.Emit (ec, leave_copy);
 
4618
                                return;
 
4619
                        }
 
4620
 
 
4621
                        EmitLoad (ec);
 
4622
 
 
4623
                        if (IsRef) {
 
4624
                                //
 
4625
                                // If we are a reference, we loaded on the stack a pointer
 
4626
                                // Now lets load the real value
 
4627
                                //
 
4628
                                ec.EmitLoadFromPtr (type);
 
4629
                        }
 
4630
 
 
4631
                        if (leave_copy) {
 
4632
                                ec.Emit (OpCodes.Dup);
 
4633
 
 
4634
                                if (IsRef) {
 
4635
                                        temp = new LocalTemporary (Type);
 
4636
                                        temp.Store (ec);
 
4637
                                }
 
4638
                        }
 
4639
                }
 
4640
 
 
4641
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
 
4642
                                        bool prepare_for_load)
 
4643
                {
 
4644
                        HoistedVariable hv = GetHoistedVariable (ec);
 
4645
                        if (hv != null) {
 
4646
                                hv.EmitAssign (ec, source, leave_copy, prepare_for_load);
 
4647
                                return;
 
4648
                        }
 
4649
 
 
4650
                        New n_source = source as New;
 
4651
                        if (n_source != null) {
 
4652
                                if (!n_source.Emit (ec, this)) {
 
4653
                                        if (leave_copy) {
 
4654
                                                EmitLoad (ec);
 
4655
                                                if (IsRef)
 
4656
                                                        ec.EmitLoadFromPtr (type);
 
4657
                                        }
 
4658
                                        return;
 
4659
                                }
 
4660
                        } else {
 
4661
                                if (IsRef)
 
4662
                                        EmitLoad (ec);
 
4663
 
 
4664
                                source.Emit (ec);
 
4665
                        }
 
4666
 
 
4667
                        if (leave_copy) {
 
4668
                                ec.Emit (OpCodes.Dup);
 
4669
                                if (IsRef) {
 
4670
                                        temp = new LocalTemporary (Type);
 
4671
                                        temp.Store (ec);
 
4672
                                }
 
4673
                        }
 
4674
 
 
4675
                        if (IsRef)
 
4676
                                ec.EmitStoreFromPtr (type);
 
4677
                        else
 
4678
                                Variable.EmitAssign (ec);
 
4679
 
 
4680
                        if (temp != null) {
 
4681
                                temp.Emit (ec);
 
4682
                                temp.Release (ec);
 
4683
                        }
 
4684
                }
 
4685
 
 
4686
 
 
4687
                public HoistedVariable GetHoistedVariable (ResolveContext rc)
 
4688
                {
 
4689
                        return GetHoistedVariable (rc.CurrentAnonymousMethod);
 
4690
                }
 
4691
 
 
4692
                public HoistedVariable GetHoistedVariable (EmitContext ec)
 
4693
                {
 
4694
                        return GetHoistedVariable (ec.CurrentAnonymousMethod);
 
4695
                }
 
4696
 
 
4697
                public override string GetSignatureForError ()
 
4698
                {
 
4699
                        return Name;
 
4700
                }
 
4701
 
 
4702
                public bool IsHoisted {
 
4703
                        get { return GetHoistedVariable ((AnonymousExpression) null) != null; }
 
4704
                }
 
4705
        }
 
4706
 
 
4707
        //
 
4708
        // Resolved reference to a local variable
 
4709
        //
 
4710
        public class LocalVariableReference : VariableReference
 
4711
        {
 
4712
                public LocalVariable local_info;
 
4713
 
 
4714
                public LocalVariableReference (LocalVariable li, Location l)
 
4715
                {
 
4716
                        this.local_info = li;
 
4717
                        loc = l;
 
4718
                }
 
4719
 
 
4720
                public override VariableInfo VariableInfo {
 
4721
                        get { return local_info.VariableInfo; }
 
4722
                }
 
4723
 
 
4724
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
 
4725
                {
 
4726
                        return local_info.HoistedVariant;
 
4727
                }
 
4728
 
 
4729
                #region Properties
 
4730
 
 
4731
                //              
 
4732
                // A local variable is always fixed
 
4733
                //
 
4734
                public override bool IsFixed {
 
4735
                        get {
 
4736
                                return true;
 
4737
                        }
 
4738
                }
 
4739
 
 
4740
                public override bool IsLockedByStatement {
 
4741
                        get {
 
4742
                                return local_info.IsLocked;
 
4743
                        }
 
4744
                        set {
 
4745
                                local_info.IsLocked = value;
 
4746
                        }
 
4747
                }
 
4748
 
 
4749
                public override bool IsRef {
 
4750
                        get { return false; }
 
4751
                }
 
4752
 
 
4753
                public override string Name {
 
4754
                        get { return local_info.Name; }
 
4755
                }
 
4756
 
 
4757
                #endregion
 
4758
 
 
4759
                public bool VerifyAssigned (ResolveContext ec)
 
4760
                {
 
4761
                        VariableInfo variable_info = local_info.VariableInfo;
 
4762
                        return variable_info == null || variable_info.IsAssigned (ec, loc);
 
4763
                }
 
4764
 
 
4765
                public override void SetHasAddressTaken ()
 
4766
                {
 
4767
                        local_info.AddressTaken = true;
 
4768
                }
 
4769
 
 
4770
                public override Expression CreateExpressionTree (ResolveContext ec)
 
4771
                {
 
4772
                        HoistedVariable hv = GetHoistedVariable (ec);
 
4773
                        if (hv != null)
 
4774
                                return hv.CreateExpressionTree ();
 
4775
 
 
4776
                        Arguments arg = new Arguments (1);
 
4777
                        arg.Add (new Argument (this));
 
4778
                        return CreateExpressionFactoryCall (ec, "Constant", arg);
 
4779
                }
 
4780
 
 
4781
                void DoResolveBase (ResolveContext ec)
 
4782
                {
 
4783
                        VerifyAssigned (ec);
 
4784
 
 
4785
                        //
 
4786
                        // If we are referencing a variable from the external block
 
4787
                        // flag it for capturing
 
4788
                        //
 
4789
                        if (ec.MustCaptureVariable (local_info)) {
 
4790
                                if (local_info.AddressTaken) {
 
4791
                                        AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc);
 
4792
                                } else if (local_info.IsFixed) {
 
4793
                                        ec.Report.Error (1764, loc,
 
4794
                                                "Cannot use fixed local `{0}' inside an anonymous method, lambda expression or query expression",
 
4795
                                                GetSignatureForError ());
 
4796
                                }
 
4797
 
 
4798
                                if (ec.IsVariableCapturingRequired) {
 
4799
                                        AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec);
 
4800
                                        storey.CaptureLocalVariable (ec, local_info);
 
4801
                                }
 
4802
                        }
 
4803
 
 
4804
                        eclass = ExprClass.Variable;
 
4805
                        type = local_info.Type;
 
4806
                }
 
4807
 
 
4808
                protected override Expression DoResolve (ResolveContext ec)
 
4809
                {
 
4810
                        local_info.SetIsUsed ();
 
4811
 
 
4812
                        DoResolveBase (ec);
 
4813
                        return this;
 
4814
                }
 
4815
 
 
4816
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
4817
                {
 
4818
                        // is out param
 
4819
                        if (right_side == EmptyExpression.OutAccess)
 
4820
                                local_info.SetIsUsed ();
 
4821
 
 
4822
                        if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) {
 
4823
                                int code;
 
4824
                                string msg;
 
4825
                                if (right_side == EmptyExpression.OutAccess) {
 
4826
                                        code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
 
4827
                                } else if (right_side == EmptyExpression.LValueMemberAccess) {
 
4828
                                        code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
 
4829
                                } else if (right_side == EmptyExpression.LValueMemberOutAccess) {
 
4830
                                        code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
 
4831
                                } else if (right_side == EmptyExpression.UnaryAddress) {
 
4832
                                        code = 459; msg = "Cannot take the address of {1} `{0}'";
 
4833
                                } else {
 
4834
                                        code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
 
4835
                                }
 
4836
                                ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
 
4837
                        } else if (VariableInfo != null) {
 
4838
                                VariableInfo.SetAssigned (ec);
 
4839
                        }
 
4840
 
 
4841
                        DoResolveBase (ec);
 
4842
 
 
4843
                        return base.DoResolveLValue (ec, right_side);
 
4844
                }
 
4845
 
 
4846
                public override int GetHashCode ()
 
4847
                {
 
4848
                        return local_info.GetHashCode ();
 
4849
                }
 
4850
 
 
4851
                public override bool Equals (object obj)
 
4852
                {
 
4853
                        LocalVariableReference lvr = obj as LocalVariableReference;
 
4854
                        if (lvr == null)
 
4855
                                return false;
 
4856
 
 
4857
                        return local_info == lvr.local_info;
 
4858
                }
 
4859
 
 
4860
                protected override ILocalVariable Variable {
 
4861
                        get { return local_info; }
 
4862
                }
 
4863
 
 
4864
                public override string ToString ()
 
4865
                {
 
4866
                        return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
 
4867
                }
 
4868
 
 
4869
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
4870
                {
 
4871
                        // Nothing
 
4872
                }
 
4873
                
 
4874
                public override object Accept (StructuralVisitor visitor)
 
4875
                {
 
4876
                        return visitor.Visit (this);
 
4877
                }
 
4878
        }
 
4879
 
 
4880
        /// <summary>
 
4881
        ///   This represents a reference to a parameter in the intermediate
 
4882
        ///   representation.
 
4883
        /// </summary>
 
4884
        public class ParameterReference : VariableReference
 
4885
        {
 
4886
                protected ParametersBlock.ParameterInfo pi;
 
4887
 
 
4888
                public ParameterReference (ParametersBlock.ParameterInfo pi, Location loc)
 
4889
                {
 
4890
                        this.pi = pi;
 
4891
                        this.loc = loc;
 
4892
                }
 
4893
 
 
4894
                #region Properties
 
4895
 
 
4896
                public override bool IsLockedByStatement {
 
4897
                        get {
 
4898
                                return pi.IsLocked;
 
4899
                        }
 
4900
                        set     {
 
4901
                                pi.IsLocked = value;
 
4902
                        }
 
4903
                }
 
4904
 
 
4905
                public override bool IsRef {
 
4906
                        get { return (pi.Parameter.ModFlags & Parameter.Modifier.ISBYREF) != 0; }
 
4907
                }
 
4908
 
 
4909
                bool HasOutModifier {
 
4910
                        get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; }
 
4911
                }
 
4912
 
 
4913
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
 
4914
                {
 
4915
                        return pi.Parameter.HoistedVariant;
 
4916
                }
 
4917
 
 
4918
                //
 
4919
                // A ref or out parameter is classified as a moveable variable, even 
 
4920
                // if the argument given for the parameter is a fixed variable
 
4921
                //              
 
4922
                public override bool IsFixed {
 
4923
                        get { return !IsRef; }
 
4924
                }
 
4925
 
 
4926
                public override string Name {
 
4927
                        get { return Parameter.Name; }
 
4928
                }
 
4929
 
 
4930
                public Parameter Parameter {
 
4931
                        get { return pi.Parameter; }
 
4932
                }
 
4933
 
 
4934
                public override VariableInfo VariableInfo {
 
4935
                        get { return pi.VariableInfo; }
 
4936
                }
 
4937
 
 
4938
                protected override ILocalVariable Variable {
 
4939
                        get { return Parameter; }
 
4940
                }
 
4941
 
 
4942
                #endregion
 
4943
 
 
4944
                public bool IsAssigned (ResolveContext ec, Location loc)
 
4945
                {
 
4946
                        // HACK: Variables are not captured in probing mode
 
4947
                        if (ec.IsInProbingMode)
 
4948
                                return true;
 
4949
                        
 
4950
                        if (!ec.DoFlowAnalysis || !HasOutModifier || ec.CurrentBranching.IsAssigned (VariableInfo))
 
4951
                                return true;
 
4952
 
 
4953
                        ec.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
 
4954
                        return false;
 
4955
                }
 
4956
 
 
4957
                public override void SetHasAddressTaken ()
 
4958
                {
 
4959
                        Parameter.HasAddressTaken = true;
 
4960
                }
 
4961
 
 
4962
                void SetAssigned (ResolveContext ec)
 
4963
                {
 
4964
                        if (HasOutModifier && ec.DoFlowAnalysis)
 
4965
                                ec.CurrentBranching.SetAssigned (VariableInfo);
 
4966
                }
 
4967
 
 
4968
                bool DoResolveBase (ResolveContext ec)
 
4969
                {
 
4970
                        if (eclass != ExprClass.Unresolved)
 
4971
                                return true;
 
4972
 
 
4973
                        type = pi.ParameterType;
 
4974
                        eclass = ExprClass.Variable;
 
4975
 
 
4976
                        //
 
4977
                        // If we are referencing a parameter from the external block
 
4978
                        // flag it for capturing
 
4979
                        //
 
4980
                        if (ec.MustCaptureVariable (pi)) {
 
4981
                                if (Parameter.HasAddressTaken)
 
4982
                                        AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc);
 
4983
 
 
4984
                                if (IsRef) {
 
4985
                                        ec.Report.Error (1628, loc,
 
4986
                                                "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier",
 
4987
                                                Name, ec.CurrentAnonymousMethod.ContainerType);
 
4988
                                }
 
4989
 
 
4990
                                if (ec.IsVariableCapturingRequired && !pi.Block.ParametersBlock.IsExpressionTree) {
 
4991
                                        AnonymousMethodStorey storey = pi.Block.Explicit.CreateAnonymousMethodStorey (ec);
 
4992
                                        storey.CaptureParameter (ec, this);
 
4993
                                }
 
4994
                        }
 
4995
 
 
4996
                        return true;
 
4997
                }
 
4998
 
 
4999
                public override int GetHashCode ()
 
5000
                {
 
5001
                        return Name.GetHashCode ();
 
5002
                }
 
5003
 
 
5004
                public override bool Equals (object obj)
 
5005
                {
 
5006
                        ParameterReference pr = obj as ParameterReference;
 
5007
                        if (pr == null)
 
5008
                                return false;
 
5009
 
 
5010
                        return Name == pr.Name;
 
5011
                }
 
5012
 
 
5013
                public override void AddressOf (EmitContext ec, AddressOp mode)
 
5014
                {
 
5015
                        //
 
5016
                        // ParameterReferences might already be a reference
 
5017
                        //
 
5018
                        if (IsRef) {
 
5019
                                EmitLoad (ec);
 
5020
                                return;
 
5021
                        }
 
5022
 
 
5023
                        base.AddressOf (ec, mode);
 
5024
                }
 
5025
                
 
5026
                protected override void CloneTo (CloneContext clonectx, Expression target)
 
5027
                {
 
5028
                        // Nothing to clone
 
5029
                        return;
 
5030
                }
 
5031
 
 
5032
                public override Expression CreateExpressionTree (ResolveContext ec)
 
5033
                {
 
5034
                        HoistedVariable hv = GetHoistedVariable (ec);
 
5035
                        if (hv != null)
 
5036
                                return hv.CreateExpressionTree ();
 
5037
 
 
5038
                        return Parameter.ExpressionTreeVariableReference ();
 
5039
                }
 
5040
 
 
5041
                //
 
5042
                // Notice that for ref/out parameters, the type exposed is not the
 
5043
                // same type exposed externally.
 
5044
                //
 
5045
                // for "ref int a":
 
5046
                //   externally we expose "int&"
 
5047
                //   here we expose       "int".
 
5048
                //
 
5049
                // We record this in "is_ref".  This means that the type system can treat
 
5050
                // the type as it is expected, but when we generate the code, we generate
 
5051
                // the alternate kind of code.
 
5052
                //
 
5053
                protected override Expression DoResolve (ResolveContext ec)
 
5054
                {
 
5055
                        if (!DoResolveBase (ec))
 
5056
                                return null;
 
5057
 
 
5058
                        // HACK: Variables are not captured in probing mode
 
5059
                        if (ec.IsInProbingMode)
 
5060
                                return this;
 
5061
 
 
5062
                        if (HasOutModifier && ec.DoFlowAnalysis &&
 
5063
                            (!ec.OmitStructFlowAnalysis || !VariableInfo.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
 
5064
                                return null;
 
5065
 
 
5066
                        return this;
 
5067
                }
 
5068
 
 
5069
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
5070
                {
 
5071
                        if (!DoResolveBase (ec))
 
5072
                                return null;
 
5073
 
 
5074
                        SetAssigned (ec);
 
5075
                        return base.DoResolveLValue (ec, right_side);
 
5076
                }
 
5077
 
 
5078
                static public void EmitLdArg (EmitContext ec, int x)
 
5079
                {
 
5080
                        switch (x) {
 
5081
                        case 0: ec.Emit (OpCodes.Ldarg_0); break;
 
5082
                        case 1: ec.Emit (OpCodes.Ldarg_1); break;
 
5083
                        case 2: ec.Emit (OpCodes.Ldarg_2); break;
 
5084
                        case 3: ec.Emit (OpCodes.Ldarg_3); break;
 
5085
                        default:
 
5086
                                if (x > byte.MaxValue)
 
5087
                                        ec.Emit (OpCodes.Ldarg, x);
 
5088
                                else
 
5089
                                        ec.Emit (OpCodes.Ldarg_S, (byte) x);
 
5090
                                break;
 
5091
                        }
 
5092
                }
 
5093
        }
 
5094
        
 
5095
        /// <summary>
 
5096
        ///   Invocation of methods or delegates.
 
5097
        /// </summary>
 
5098
        public class Invocation : ExpressionStatement
 
5099
        {
 
5100
                protected Arguments arguments;
 
5101
                protected Expression expr;
 
5102
                protected MethodGroupExpr mg;
 
5103
 
 
5104
                //
 
5105
                // arguments is an ArrayList, but we do not want to typecast,
 
5106
                // as it might be null.
 
5107
                //
 
5108
                public Invocation (Expression expr, Arguments arguments)
 
5109
                {
 
5110
                        this.expr = expr;               
 
5111
                        this.arguments = arguments;
 
5112
                        if (expr != null)
 
5113
                                loc = expr.Location;
 
5114
                }
 
5115
 
 
5116
                #region Properties
 
5117
                public Arguments Arguments {
 
5118
                        get {
 
5119
                                return arguments;
 
5120
                        }
 
5121
                }
 
5122
                
 
5123
                public Expression Expression {
 
5124
                        get {
 
5125
                                return expr;
 
5126
                        }
 
5127
                }
 
5128
                #endregion
 
5129
 
 
5130
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
5131
                {
 
5132
                        Invocation target = (Invocation) t;
 
5133
 
 
5134
                        if (arguments != null)
 
5135
                                target.arguments = arguments.Clone (clonectx);
 
5136
 
 
5137
                        target.expr = expr.Clone (clonectx);
 
5138
                }
 
5139
 
 
5140
 
 
5141
                public override Expression CreateExpressionTree (ResolveContext ec)
 
5142
                {
 
5143
                        Expression instance = mg.IsInstance ?
 
5144
                                mg.InstanceExpression.CreateExpressionTree (ec) :
 
5145
                                new NullLiteral (loc);
 
5146
 
 
5147
                        var args = Arguments.CreateForExpressionTree (ec, arguments,
 
5148
                                instance,
 
5149
                                mg.CreateExpressionTree (ec));
 
5150
 
 
5151
                        return CreateExpressionFactoryCall (ec, "Call", args);
 
5152
                }
 
5153
 
 
5154
                protected override Expression DoResolve (ResolveContext ec)
 
5155
                {
 
5156
                        Expression member_expr;
 
5157
                        var atn = expr as ATypeNameExpression;
 
5158
                        if (atn != null) {
 
5159
                                member_expr = atn.LookupNameExpression (ec, MemberLookupRestrictions.InvocableOnly | MemberLookupRestrictions.ReadAccess);
 
5160
                                if (member_expr != null)
 
5161
                                        member_expr = member_expr.Resolve (ec);
 
5162
                        } else {
 
5163
                                member_expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
 
5164
                        }
 
5165
 
 
5166
                        if (member_expr == null)
 
5167
                                return null;
 
5168
 
 
5169
                        //
 
5170
                        // Next, evaluate all the expressions in the argument list
 
5171
                        //
 
5172
                        bool dynamic_arg = false;
 
5173
                        if (arguments != null)
 
5174
                                arguments.Resolve (ec, out dynamic_arg);
 
5175
 
 
5176
                        TypeSpec expr_type = member_expr.Type;
 
5177
                        if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
5178
                                return DoResolveDynamic (ec, member_expr);
 
5179
 
 
5180
                        mg = member_expr as MethodGroupExpr;
 
5181
                        Expression invoke = null;
 
5182
 
 
5183
                        if (mg == null) {
 
5184
                                if (expr_type != null && TypeManager.IsDelegateType (expr_type)) {
 
5185
                                        invoke = new DelegateInvocation (member_expr, arguments, loc);
 
5186
                                        invoke = invoke.Resolve (ec);
 
5187
                                        if (invoke == null || !dynamic_arg)
 
5188
                                                return invoke;
 
5189
                                } else {
 
5190
                                        if (member_expr is RuntimeValueExpression) {
 
5191
                                                ec.Report.Error (Report.RuntimeErrorId, loc, "Cannot invoke a non-delegate type `{0}'",
 
5192
                                                        member_expr.Type.GetSignatureForError ()); ;
 
5193
                                                return null;
 
5194
                                        }
 
5195
 
 
5196
                                        MemberExpr me = member_expr as MemberExpr;
 
5197
                                        if (me == null) {
 
5198
                                                member_expr.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc);
 
5199
                                                return null;
 
5200
                                        }
 
5201
 
 
5202
                                        ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate",
 
5203
                                                        member_expr.GetSignatureForError ());
 
5204
                                        return null;
 
5205
                                }
 
5206
                        }
 
5207
 
 
5208
                        if (invoke == null) {
 
5209
                                mg = DoResolveOverload (ec);
 
5210
                                if (mg == null)
 
5211
                                        return null;
 
5212
                        }
 
5213
 
 
5214
                        if (dynamic_arg)
 
5215
                                return DoResolveDynamic (ec, member_expr);
 
5216
 
 
5217
                        var method = mg.BestCandidate;
 
5218
                        type = mg.BestCandidateReturnType;
 
5219
                
 
5220
                        if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) {
 
5221
                                if (mg.IsBase)
 
5222
                                        ec.Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor");
 
5223
                                else
 
5224
                                        ec.Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available");
 
5225
                                return null;
 
5226
                        }
 
5227
 
 
5228
                        IsSpecialMethodInvocation (ec, method, loc);
 
5229
                        
 
5230
                        eclass = ExprClass.Value;
 
5231
                        return this;
 
5232
                }
 
5233
 
 
5234
                protected virtual Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr)
 
5235
                {
 
5236
                        Arguments args;
 
5237
                        DynamicMemberBinder dmb = memberExpr as DynamicMemberBinder;
 
5238
                        if (dmb != null) {
 
5239
                                args = dmb.Arguments;
 
5240
                                if (arguments != null)
 
5241
                                        args.AddRange (arguments);
 
5242
                        } else if (mg == null) {
 
5243
                                if (arguments == null)
 
5244
                                        args = new Arguments (1);
 
5245
                                else
 
5246
                                        args = arguments;
 
5247
 
 
5248
                                args.Insert (0, new Argument (memberExpr));
 
5249
                                this.expr = null;
 
5250
                        } else {
 
5251
                                if (mg.IsBase) {
 
5252
                                        ec.Report.Error (1971, loc,
 
5253
                                                "The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access",
 
5254
                                                mg.Name);
 
5255
                                        return null;
 
5256
                                }
 
5257
 
 
5258
                                if (arguments == null)
 
5259
                                        args = new Arguments (1);
 
5260
                                else
 
5261
                                        args = arguments;
 
5262
 
 
5263
                                MemberAccess ma = expr as MemberAccess;
 
5264
                                if (ma != null) {
 
5265
                                        var left_type = ma.LeftExpression as TypeExpr;
 
5266
                                        if (left_type != null) {
 
5267
                                                args.Insert (0, new Argument (new TypeOf (left_type.Type, loc).Resolve (ec), Argument.AType.DynamicTypeName));
 
5268
                                        } else {
 
5269
                                                //
 
5270
                                                // Any value type has to be pass as by-ref to get back the same
 
5271
                                                // instance on which the member was called
 
5272
                                                //
 
5273
                                                var mod = TypeSpec.IsValueType (ma.LeftExpression.Type) ? Argument.AType.Ref : Argument.AType.None;
 
5274
                                                args.Insert (0, new Argument (ma.LeftExpression.Resolve (ec), mod));
 
5275
                                        }
 
5276
                                } else {        // is SimpleName
 
5277
                                        if (ec.IsStatic) {
 
5278
                                                args.Insert (0, new Argument (new TypeOf (ec.CurrentType, loc).Resolve (ec), Argument.AType.DynamicTypeName));
 
5279
                                        } else {
 
5280
                                                args.Insert (0, new Argument (new This (loc).Resolve (ec)));
 
5281
                                        }
 
5282
                                }
 
5283
                        }
 
5284
 
 
5285
                        return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec);
 
5286
                }
 
5287
 
 
5288
                protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec)
 
5289
                {
 
5290
                        return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None);
 
5291
                }
 
5292
 
 
5293
                static MetaType[] GetVarargsTypes (MethodSpec mb, Arguments arguments)
 
5294
                {
 
5295
                        AParametersCollection pd = mb.Parameters;
 
5296
 
 
5297
                        Argument a = arguments[pd.Count - 1];
 
5298
                        Arglist list = (Arglist) a.Expr;
 
5299
 
 
5300
                        return list.ArgumentTypes;
 
5301
                }
 
5302
 
 
5303
                //
 
5304
                // If a member is a method or event, or if it is a constant, field or property of either a delegate type
 
5305
                // or the type dynamic, then the member is invocable
 
5306
                //
 
5307
                public static bool IsMemberInvocable (MemberSpec member)
 
5308
                {
 
5309
                        switch (member.Kind) {
 
5310
                        case MemberKind.Event:
 
5311
                                return true;
 
5312
                        case MemberKind.Field:
 
5313
                        case MemberKind.Property:
 
5314
                                var m = member as IInterfaceMemberSpec;
 
5315
                                return m.MemberType.IsDelegate || m.MemberType.BuiltinType == BuiltinTypeSpec.Type.Dynamic;
 
5316
                        default:
 
5317
                                return false;
 
5318
                        }
 
5319
                }
 
5320
 
 
5321
                public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodSpec method, Location loc)
 
5322
                {
 
5323
                        if (!method.IsReservedMethod)
 
5324
                                return false;
 
5325
 
 
5326
                        if (ec.HasSet (ResolveContext.Options.InvokeSpecialName) || ec.CurrentMemberDefinition.IsCompilerGenerated)
 
5327
                                return false;
 
5328
 
 
5329
                        ec.Report.SymbolRelatedToPreviousError (method);
 
5330
                        ec.Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor",
 
5331
                                method.GetSignatureForError ());
 
5332
        
 
5333
                        return true;
 
5334
                }
 
5335
 
 
5336
                //
 
5337
                // Used to decide whether call or callvirt is needed
 
5338
                //
 
5339
                static bool IsVirtualCallRequired (Expression instance, MethodSpec method)
 
5340
                {
 
5341
                        //
 
5342
                        // There are 2 scenarious where we emit callvirt
 
5343
                        //
 
5344
                        // Case 1: A method is virtual and it's not used to call base
 
5345
                        // Case 2: A method instance expression can be null. In this casen callvirt ensures
 
5346
                        // correct NRE exception when the method is called
 
5347
                        //
 
5348
                        var decl_type = method.DeclaringType;
 
5349
                        if (decl_type.IsStruct || decl_type.IsEnum)
 
5350
                                return false;
 
5351
 
 
5352
                        if (instance is BaseThis)
 
5353
                                return false;
 
5354
 
 
5355
                        //
 
5356
                        // It's non-virtual and will never be null
 
5357
                        //
 
5358
                        if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation))
 
5359
                                return false;
 
5360
 
 
5361
                        return true;
 
5362
                }
 
5363
 
 
5364
                /// <remarks>
 
5365
                ///   is_base tells whether we want to force the use of the `call'
 
5366
                ///   opcode instead of using callvirt.  Call is required to call
 
5367
                ///   a specific method, while callvirt will always use the most
 
5368
                ///   recent method in the vtable.
 
5369
                ///
 
5370
                ///   is_static tells whether this is an invocation on a static method
 
5371
                ///
 
5372
                ///   instance_expr is an expression that represents the instance
 
5373
                ///   it must be non-null if is_static is false.
 
5374
                ///
 
5375
                ///   method is the method to invoke.
 
5376
                ///
 
5377
                ///   Arguments is the list of arguments to pass to the method or constructor.
 
5378
                /// </remarks>
 
5379
                public static void EmitCall (EmitContext ec, Expression instance_expr,
 
5380
                                             MethodSpec method, Arguments Arguments, Location loc)
 
5381
                {
 
5382
                        EmitCall (ec, instance_expr, method, Arguments, loc, false, false);
 
5383
                }
 
5384
                
 
5385
                // `dup_args' leaves an extra copy of the arguments on the stack
 
5386
                // `omit_args' does not leave any arguments at all.
 
5387
                // So, basically, you could make one call with `dup_args' set to true,
 
5388
                // and then another with `omit_args' set to true, and the two calls
 
5389
                // would have the same set of arguments. However, each argument would
 
5390
                // only have been evaluated once.
 
5391
                public static void EmitCall (EmitContext ec, Expression instance_expr,
 
5392
                                             MethodSpec method, Arguments Arguments, Location loc,
 
5393
                                             bool dup_args, bool omit_args)
 
5394
                {
 
5395
                        LocalTemporary this_arg = null;
 
5396
 
 
5397
                        // Speed up the check by not doing it on not allowed targets
 
5398
                        if (method.ReturnType.Kind == MemberKind.Void && method.IsConditionallyExcluded (ec.Module.Compiler, loc))
 
5399
                                return;
 
5400
 
 
5401
                        OpCode call_op;
 
5402
                        TypeSpec iexpr_type;
 
5403
 
 
5404
                        if (method.IsStatic) {
 
5405
                                iexpr_type = null;
 
5406
                                call_op = OpCodes.Call;
 
5407
                        } else {
 
5408
                                iexpr_type = instance_expr.Type;
 
5409
 
 
5410
                                if (IsVirtualCallRequired (instance_expr, method)) {
 
5411
                                        call_op = OpCodes.Callvirt;
 
5412
                                } else {
 
5413
                                        call_op = OpCodes.Call;
 
5414
                                }
 
5415
 
 
5416
                                //
 
5417
                                // If this is ourselves, push "this"
 
5418
                                //
 
5419
                                if (!omit_args) {
 
5420
                                        TypeSpec t = iexpr_type;
 
5421
 
 
5422
                                        //
 
5423
                                        // Push the instance expression
 
5424
                                        //
 
5425
                                        if ((iexpr_type.IsStruct && (call_op == OpCodes.Callvirt || (call_op == OpCodes.Call && method.DeclaringType == iexpr_type))) ||
 
5426
                                                iexpr_type.IsGenericParameter || method.DeclaringType.IsNullableType) {
 
5427
                                                //
 
5428
                                                // If the expression implements IMemoryLocation, then
 
5429
                                                // we can optimize and use AddressOf on the
 
5430
                                                // return.
 
5431
                                                //
 
5432
                                                // If not we have to use some temporary storage for
 
5433
                                                // it.
 
5434
                                                var iml = instance_expr as IMemoryLocation;
 
5435
                                                if (iml != null) {
 
5436
                                                        iml.AddressOf (ec, AddressOp.Load);
 
5437
                                                } else {
 
5438
                                                        LocalTemporary temp = new LocalTemporary (iexpr_type);
 
5439
                                                        instance_expr.Emit (ec);
 
5440
                                                        temp.Store (ec);
 
5441
                                                        temp.AddressOf (ec, AddressOp.Load);
 
5442
                                                }
 
5443
 
 
5444
                                                // avoid the overhead of doing this all the time.
 
5445
                                                if (dup_args)
 
5446
                                                        t = ReferenceContainer.MakeType (ec.Module, iexpr_type);
 
5447
                                        } else if (iexpr_type.IsEnum || iexpr_type.IsStruct) {
 
5448
                                                instance_expr.Emit (ec);
 
5449
                                                ec.Emit (OpCodes.Box, iexpr_type);
 
5450
                                                t = iexpr_type = ec.BuiltinTypes.Object;
 
5451
                                        } else {
 
5452
                                                instance_expr.Emit (ec);
 
5453
                                        }
 
5454
 
 
5455
                                        if (dup_args) {
 
5456
                                                ec.Emit (OpCodes.Dup);
 
5457
                                                if (Arguments != null && Arguments.Count != 0) {
 
5458
                                                        this_arg = new LocalTemporary (t);
 
5459
                                                        this_arg.Store (ec);
 
5460
                                                }
 
5461
                                        }
 
5462
                                }
 
5463
                        }
 
5464
 
 
5465
                        if (!omit_args && Arguments != null) {
 
5466
                                var dup_arg_exprs = Arguments.Emit (ec, dup_args);
 
5467
                                if (dup_args) {
 
5468
                                        this_arg.Emit (ec);
 
5469
                                        LocalTemporary lt;
 
5470
                                        foreach (var dup in dup_arg_exprs) {
 
5471
                                                dup.Emit (ec);
 
5472
                                                lt = dup as LocalTemporary;
 
5473
                                                if (lt != null)
 
5474
                                                        lt.Release (ec);
 
5475
                                        }
 
5476
                                }
 
5477
                        }
 
5478
 
 
5479
                        if (call_op == OpCodes.Callvirt && (iexpr_type.IsGenericParameter || iexpr_type.IsStruct)) {
 
5480
                                ec.Emit (OpCodes.Constrained, iexpr_type);
 
5481
                        }
 
5482
 
 
5483
                        if (method.Parameters.HasArglist) {
 
5484
                                var varargs_types = GetVarargsTypes (method, Arguments);
 
5485
                                ec.Emit (call_op, method, varargs_types);
 
5486
                                return;
 
5487
                        }
 
5488
 
 
5489
                        //
 
5490
                        // If you have:
 
5491
                        // this.DoFoo ();
 
5492
                        // and DoFoo is not virtual, you can omit the callvirt,
 
5493
                        // because you don't need the null checking behavior.
 
5494
                        //
 
5495
                        ec.Emit (call_op, method);
 
5496
                }
 
5497
 
 
5498
                public override void Emit (EmitContext ec)
 
5499
                {
 
5500
                        mg.EmitCall (ec, arguments);
 
5501
                }
 
5502
                
 
5503
                public override void EmitStatement (EmitContext ec)
 
5504
                {
 
5505
                        Emit (ec);
 
5506
 
 
5507
                        // 
 
5508
                        // Pop the return value if there is one
 
5509
                        //
 
5510
                        if (type.Kind != MemberKind.Void)
 
5511
                                ec.Emit (OpCodes.Pop);
 
5512
                }
 
5513
 
 
5514
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
5515
                {
 
5516
                        return MakeExpression (ctx, mg.InstanceExpression, mg.BestCandidate, arguments);
 
5517
                }
 
5518
 
 
5519
                public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args)
 
5520
                {
 
5521
#if STATIC
 
5522
                        throw new NotSupportedException ();
 
5523
#else
 
5524
                        var instance_expr = instance == null ? null : instance.MakeExpression (ctx);
 
5525
                        return SLE.Expression.Call (instance_expr, (MethodInfo) mi.GetMetaInfo (), Arguments.MakeExpression (args, ctx));
 
5526
#endif
 
5527
                }
 
5528
                public override object Accept (StructuralVisitor visitor)
 
5529
                {
 
5530
                        return visitor.Visit (this);
 
5531
                }
 
5532
        }
 
5533
 
 
5534
        //
 
5535
        // Implements simple new expression 
 
5536
        //
 
5537
        public class New : ExpressionStatement, IMemoryLocation
 
5538
        {
 
5539
                protected Arguments arguments;
 
5540
 
 
5541
                //
 
5542
                // During bootstrap, it contains the RequestedType,
 
5543
                // but if `type' is not null, it *might* contain a NewDelegate
 
5544
                // (because of field multi-initialization)
 
5545
                //
 
5546
                protected Expression RequestedType;
 
5547
 
 
5548
                protected MethodSpec method;
 
5549
 
 
5550
                public New (Expression requested_type, Arguments arguments, Location l)
 
5551
                {
 
5552
                        RequestedType = requested_type;
 
5553
                        this.arguments = arguments;
 
5554
                        loc = l;
 
5555
                }
 
5556
 
 
5557
                #region Properties
 
5558
                public Arguments Arguments {
 
5559
                        get {
 
5560
                                return arguments;
 
5561
                        }
 
5562
                }
 
5563
 
 
5564
                public Expression TypeRequested {
 
5565
                        get {
 
5566
                                return RequestedType;
 
5567
                        }
 
5568
                }
 
5569
 
 
5570
                //
 
5571
                // Returns true for resolved `new S()'
 
5572
                //
 
5573
                public bool IsDefaultStruct {
 
5574
                        get {
 
5575
                                return arguments == null && type.IsStruct && GetType () == typeof (New);
 
5576
                        }
 
5577
                }
 
5578
 
 
5579
                #endregion
 
5580
 
 
5581
                /// <summary>
 
5582
                /// Converts complex core type syntax like 'new int ()' to simple constant
 
5583
                /// </summary>
 
5584
                public static Constant Constantify (TypeSpec t, Location loc)
 
5585
                {
 
5586
                        switch (t.BuiltinType) {
 
5587
                        case BuiltinTypeSpec.Type.Int:
 
5588
                                return new IntConstant (t, 0, loc);
 
5589
                        case BuiltinTypeSpec.Type.UInt:
 
5590
                                return new UIntConstant (t, 0, loc);
 
5591
                        case BuiltinTypeSpec.Type.Long:
 
5592
                                return new LongConstant (t, 0, loc);
 
5593
                        case BuiltinTypeSpec.Type.ULong:
 
5594
                                return new ULongConstant (t, 0, loc);
 
5595
                        case BuiltinTypeSpec.Type.Float:
 
5596
                                return new FloatConstant (t, 0, loc);
 
5597
                        case BuiltinTypeSpec.Type.Double:
 
5598
                                return new DoubleConstant (t, 0, loc);
 
5599
                        case BuiltinTypeSpec.Type.Short:
 
5600
                                return new ShortConstant (t, 0, loc);
 
5601
                        case BuiltinTypeSpec.Type.UShort:
 
5602
                                return new UShortConstant (t, 0, loc);
 
5603
                        case BuiltinTypeSpec.Type.SByte:
 
5604
                                return new SByteConstant (t, 0, loc);
 
5605
                        case BuiltinTypeSpec.Type.Byte:
 
5606
                                return new ByteConstant (t, 0, loc);
 
5607
                        case BuiltinTypeSpec.Type.Char:
 
5608
                                return new CharConstant (t, '\0', loc);
 
5609
                        case BuiltinTypeSpec.Type.Bool:
 
5610
                                return new BoolConstant (t, false, loc);
 
5611
                        case BuiltinTypeSpec.Type.Decimal:
 
5612
                                return new DecimalConstant (t, 0, loc);
 
5613
                        }
 
5614
 
 
5615
                        if (t.IsEnum)
 
5616
                                return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t), loc), t);
 
5617
 
 
5618
                        if (t.IsNullableType)
 
5619
                                return Nullable.LiftedNull.Create (t, loc);
 
5620
 
 
5621
                        return null;
 
5622
                }
 
5623
 
 
5624
                //
 
5625
                // Checks whether the type is an interface that has the
 
5626
                // [ComImport, CoClass] attributes and must be treated
 
5627
                // specially
 
5628
                //
 
5629
                public Expression CheckComImport (ResolveContext ec)
 
5630
                {
 
5631
                        if (!type.IsInterface)
 
5632
                                return null;
 
5633
 
 
5634
                        //
 
5635
                        // Turn the call into:
 
5636
                        // (the-interface-stated) (new class-referenced-in-coclassattribute ())
 
5637
                        //
 
5638
                        var real_class = type.MemberDefinition.GetAttributeCoClass ();
 
5639
                        if (real_class == null)
 
5640
                                return null;
 
5641
 
 
5642
                        New proxy = new New (new TypeExpression (real_class, loc), arguments, loc);
 
5643
                        Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc);
 
5644
                        return cast.Resolve (ec);
 
5645
                }
 
5646
 
 
5647
                public override Expression CreateExpressionTree (ResolveContext ec)
 
5648
                {
 
5649
                        Arguments args;
 
5650
                        if (method == null) {
 
5651
                                args = new Arguments (1);
 
5652
                                args.Add (new Argument (new TypeOf (type, loc)));
 
5653
                        } else {
 
5654
                                args = Arguments.CreateForExpressionTree (ec,
 
5655
                                        arguments, new TypeOfMethod (method, loc));
 
5656
                        }
 
5657
 
 
5658
                        return CreateExpressionFactoryCall (ec, "New", args);
 
5659
                }
 
5660
                
 
5661
                protected override Expression DoResolve (ResolveContext ec)
 
5662
                {
 
5663
                        type = RequestedType.ResolveAsType (ec);
 
5664
                        if (type == null)
 
5665
                                return null;
 
5666
 
 
5667
                        eclass = ExprClass.Value;
 
5668
 
 
5669
                        if (type.IsPointer) {
 
5670
                                ec.Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression",
 
5671
                                        TypeManager.CSharpName (type));
 
5672
                                return null;
 
5673
                        }
 
5674
 
 
5675
                        if (arguments == null) {
 
5676
                                Constant c = Constantify (type, RequestedType.Location);
 
5677
                                if (c != null)
 
5678
                                        return ReducedExpression.Create (c, this);
 
5679
                        }
 
5680
 
 
5681
                        if (TypeManager.IsDelegateType (type)) {
 
5682
                                return (new NewDelegate (type, arguments, loc)).Resolve (ec);
 
5683
                        }
 
5684
 
 
5685
                        var tparam = type as TypeParameterSpec;
 
5686
                        if (tparam != null) {
 
5687
                                //
 
5688
                                // Check whether the type of type parameter can be constructed. BaseType can be a struct for method overrides
 
5689
                                // where type parameter constraint is inflated to struct
 
5690
                                //
 
5691
                                if ((tparam.SpecialConstraint & (SpecialConstraint.Struct | SpecialConstraint.Constructor)) == 0 && !tparam.BaseType.IsStruct) {
 
5692
                                        ec.Report.Error (304, loc,
 
5693
                                                "Cannot create an instance of the variable type `{0}' because it does not have the new() constraint",
 
5694
                                                TypeManager.CSharpName (type));
 
5695
                                }
 
5696
 
 
5697
                                if ((arguments != null) && (arguments.Count != 0)) {
 
5698
                                        ec.Report.Error (417, loc,
 
5699
                                                "`{0}': cannot provide arguments when creating an instance of a variable type",
 
5700
                                                TypeManager.CSharpName (type));
 
5701
                                }
 
5702
 
 
5703
                                return this;
 
5704
                        }
 
5705
 
 
5706
                        if (type.IsStatic) {
 
5707
                                ec.Report.SymbolRelatedToPreviousError (type);
 
5708
                                ec.Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type));
 
5709
                                return null;
 
5710
                        }
 
5711
 
 
5712
                        if (type.IsInterface || type.IsAbstract){
 
5713
                                if (!TypeManager.IsGenericType (type)) {
 
5714
                                        RequestedType = CheckComImport (ec);
 
5715
                                        if (RequestedType != null)
 
5716
                                                return RequestedType;
 
5717
                                }
 
5718
                                
 
5719
                                ec.Report.SymbolRelatedToPreviousError (type);
 
5720
                                ec.Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type));
 
5721
                                return null;
 
5722
                        }
 
5723
 
 
5724
                        //
 
5725
                        // Any struct always defines parameterless constructor
 
5726
                        //
 
5727
                        if (type.IsStruct && arguments == null)
 
5728
                                return this;
 
5729
 
 
5730
                        bool dynamic;
 
5731
                        if (arguments != null) {
 
5732
                                arguments.Resolve (ec, out dynamic);
 
5733
                        } else {
 
5734
                                dynamic = false;
 
5735
                        }
 
5736
 
 
5737
                        method = ConstructorLookup (ec, type, ref arguments, loc);
 
5738
 
 
5739
                        if (dynamic) {
 
5740
                                arguments.Insert (0, new Argument (new TypeOf (type, loc).Resolve (ec), Argument.AType.DynamicTypeName));
 
5741
                                return new DynamicConstructorBinder (type, arguments, loc).Resolve (ec);
 
5742
                        }
 
5743
 
 
5744
                        return this;
 
5745
                }
 
5746
 
 
5747
                bool DoEmitTypeParameter (EmitContext ec)
 
5748
                {
 
5749
                        var m = ec.Module.PredefinedMembers.ActivatorCreateInstance.Resolve (loc);
 
5750
                        if (m == null)
 
5751
                                return true;
 
5752
 
 
5753
                        var ctor_factory = m.MakeGenericMethod (ec.MemberContext, type);
 
5754
                        var tparam = (TypeParameterSpec) type;
 
5755
 
 
5756
                        if (tparam.IsReferenceType) {
 
5757
                                ec.Emit (OpCodes.Call, ctor_factory);
 
5758
                                return true;
 
5759
                        }
 
5760
 
 
5761
                        // Allow DoEmit() to be called multiple times.
 
5762
                        // We need to create a new LocalTemporary each time since
 
5763
                        // you can't share LocalBuilders among ILGeneators.
 
5764
                        LocalTemporary temp = new LocalTemporary (type);
 
5765
 
 
5766
                        Label label_activator = ec.DefineLabel ();
 
5767
                        Label label_end = ec.DefineLabel ();
 
5768
 
 
5769
                        temp.AddressOf (ec, AddressOp.Store);
 
5770
                        ec.Emit (OpCodes.Initobj, type);
 
5771
 
 
5772
                        temp.Emit (ec);
 
5773
                        ec.Emit (OpCodes.Box, type);
 
5774
                        ec.Emit (OpCodes.Brfalse, label_activator);
 
5775
 
 
5776
                        temp.AddressOf (ec, AddressOp.Store);
 
5777
                        ec.Emit (OpCodes.Initobj, type);
 
5778
                        temp.Emit (ec);
 
5779
                        ec.Emit (OpCodes.Br_S, label_end);
 
5780
 
 
5781
                        ec.MarkLabel (label_activator);
 
5782
 
 
5783
                        ec.Emit (OpCodes.Call, ctor_factory);
 
5784
                        ec.MarkLabel (label_end);
 
5785
                        return true;
 
5786
                }
 
5787
 
 
5788
                //
 
5789
                // This Emit can be invoked in two contexts:
 
5790
                //    * As a mechanism that will leave a value on the stack (new object)
 
5791
                //    * As one that wont (init struct)
 
5792
                //
 
5793
                // If we are dealing with a ValueType, we have a few
 
5794
                // situations to deal with:
 
5795
                //
 
5796
                //    * The target is a ValueType, and we have been provided
 
5797
                //      the instance (this is easy, we are being assigned).
 
5798
                //
 
5799
                //    * The target of New is being passed as an argument,
 
5800
                //      to a boxing operation or a function that takes a
 
5801
                //      ValueType.
 
5802
                //
 
5803
                //      In this case, we need to create a temporary variable
 
5804
                //      that is the argument of New.
 
5805
                //
 
5806
                // Returns whether a value is left on the stack
 
5807
                //
 
5808
                // *** Implementation note ***
 
5809
                //
 
5810
                // To benefit from this optimization, each assignable expression
 
5811
                // has to manually cast to New and call this Emit.
 
5812
                //
 
5813
                // TODO: It's worth to implement it for arrays and fields
 
5814
                //
 
5815
                public virtual bool Emit (EmitContext ec, IMemoryLocation target)
 
5816
                {
 
5817
                        bool is_value_type = TypeSpec.IsValueType (type);
 
5818
                        VariableReference vr = target as VariableReference;
 
5819
 
 
5820
                        if (target != null && is_value_type && (vr != null || method == null)) {
 
5821
                                target.AddressOf (ec, AddressOp.Store);
 
5822
                        } else if (vr != null && vr.IsRef) {
 
5823
                                vr.EmitLoad (ec);
 
5824
                        }
 
5825
                        
 
5826
                        if (arguments != null)
 
5827
                                arguments.Emit (ec);
 
5828
 
 
5829
                        if (is_value_type) {
 
5830
                                if (method == null) {
 
5831
                                        ec.Emit (OpCodes.Initobj, type);
 
5832
                                        return false;
 
5833
                                }
 
5834
 
 
5835
                                if (vr != null) {
 
5836
                                        ec.Emit (OpCodes.Call, method);
 
5837
                                        return false;
 
5838
                                }
 
5839
                        }
 
5840
                        
 
5841
                        if (type is TypeParameterSpec)
 
5842
                                return DoEmitTypeParameter (ec);                        
 
5843
 
 
5844
                        ec.Emit (OpCodes.Newobj, method);
 
5845
                        return true;
 
5846
                }
 
5847
 
 
5848
                public override void Emit (EmitContext ec)
 
5849
                {
 
5850
                        LocalTemporary v = null;
 
5851
                        if (method == null && TypeSpec.IsValueType (type)) {
 
5852
                                // TODO: Use temporary variable from pool
 
5853
                                v = new LocalTemporary (type);
 
5854
                        }
 
5855
 
 
5856
                        if (!Emit (ec, v))
 
5857
                                v.Emit (ec);
 
5858
                }
 
5859
                
 
5860
                public override void EmitStatement (EmitContext ec)
 
5861
                {
 
5862
                        LocalTemporary v = null;
 
5863
                        if (method == null && TypeSpec.IsValueType (type)) {
 
5864
                                // TODO: Use temporary variable from pool
 
5865
                                v = new LocalTemporary (type);
 
5866
                        }
 
5867
 
 
5868
                        if (Emit (ec, v))
 
5869
                                ec.Emit (OpCodes.Pop);
 
5870
                }
 
5871
 
 
5872
                public void AddressOf (EmitContext ec, AddressOp mode)
 
5873
                {
 
5874
                        EmitAddressOf (ec, mode);
 
5875
                }
 
5876
 
 
5877
                protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode)
 
5878
                {
 
5879
                        LocalTemporary value_target = new LocalTemporary (type);
 
5880
 
 
5881
                        if (type is TypeParameterSpec) {
 
5882
                                DoEmitTypeParameter (ec);
 
5883
                                value_target.Store (ec);
 
5884
                                value_target.AddressOf (ec, mode);
 
5885
                                return value_target;
 
5886
                        }
 
5887
 
 
5888
                        value_target.AddressOf (ec, AddressOp.Store);
 
5889
 
 
5890
                        if (method == null) {
 
5891
                                ec.Emit (OpCodes.Initobj, type);
 
5892
                        } else {
 
5893
                                if (arguments != null)
 
5894
                                        arguments.Emit (ec);
 
5895
 
 
5896
                                ec.Emit (OpCodes.Call, method);
 
5897
                        }
 
5898
                        
 
5899
                        value_target.AddressOf (ec, mode);
 
5900
                        return value_target;
 
5901
                }
 
5902
 
 
5903
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
5904
                {
 
5905
                        New target = (New) t;
 
5906
 
 
5907
                        target.RequestedType = RequestedType.Clone (clonectx);
 
5908
                        if (arguments != null){
 
5909
                                target.arguments = arguments.Clone (clonectx);
 
5910
                        }
 
5911
                }
 
5912
 
 
5913
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
5914
                {
 
5915
#if STATIC
 
5916
                        return base.MakeExpression (ctx);
 
5917
#else
 
5918
                        return SLE.Expression.New ((ConstructorInfo) method.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx));
 
5919
#endif
 
5920
                }
 
5921
                
 
5922
                public override object Accept (StructuralVisitor visitor)
 
5923
                {
 
5924
                        return visitor.Visit (this);
 
5925
                }
 
5926
        }
 
5927
 
 
5928
        //
 
5929
        // Array initializer expression, the expression is allowed in
 
5930
        // variable or field initialization only which makes it tricky as
 
5931
        // the type has to be infered based on the context either from field
 
5932
        // type or variable type (think of multiple declarators)
 
5933
        //
 
5934
        public class ArrayInitializer : Expression
 
5935
        {
 
5936
                List<Expression> elements;
 
5937
                BlockVariableDeclaration variable;
 
5938
 
 
5939
                public ArrayInitializer (List<Expression> init, Location loc)
 
5940
                {
 
5941
                        elements = init;
 
5942
                        this.loc = loc;
 
5943
                }
 
5944
 
 
5945
                public ArrayInitializer (int count, Location loc)
 
5946
                        : this (new List<Expression> (count), loc)
 
5947
                {
 
5948
                }
 
5949
 
 
5950
                public ArrayInitializer (Location loc)
 
5951
                        : this (4, loc)
 
5952
                {
 
5953
                }
 
5954
 
 
5955
                #region Properties
 
5956
 
 
5957
                public int Count {
 
5958
                        get { return elements.Count; }
 
5959
                }
 
5960
 
 
5961
                public Expression this [int index] {
 
5962
                        get {
 
5963
                                return elements [index];
 
5964
                        }
 
5965
                }
 
5966
 
 
5967
                public BlockVariableDeclaration VariableDeclaration {
 
5968
                        get {
 
5969
                                return variable;
 
5970
                        }
 
5971
                        set {
 
5972
                                variable = value;
 
5973
                        }
 
5974
                }
 
5975
 
 
5976
                public List<Expression> Elements {
 
5977
                        get {
 
5978
                                return this.elements;
 
5979
                        }
 
5980
                }
 
5981
                #endregion
 
5982
 
 
5983
                public void Add (Expression expr)
 
5984
                {
 
5985
                        elements.Add (expr);
 
5986
                }
 
5987
 
 
5988
                public override Expression CreateExpressionTree (ResolveContext ec)
 
5989
                {
 
5990
                        throw new NotSupportedException ("ET");
 
5991
                }
 
5992
 
 
5993
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
5994
                {
 
5995
                        var target = (ArrayInitializer) t;
 
5996
 
 
5997
                        target.elements = new List<Expression> (elements.Count);
 
5998
                        foreach (var element in elements)
 
5999
                                target.elements.Add (element.Clone (clonectx));
 
6000
                }
 
6001
 
 
6002
                protected override Expression DoResolve (ResolveContext rc)
 
6003
                {
 
6004
                        var current_field = rc.CurrentMemberDefinition as FieldBase;
 
6005
                        TypeExpression type;
 
6006
                        if (current_field != null) {
 
6007
                                type = new TypeExpression (current_field.MemberType, current_field.Location);
 
6008
                        } else if (variable != null) {
 
6009
                                if (variable.TypeExpression is VarExpr) {
 
6010
                                        rc.Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer");
 
6011
                                        return EmptyExpression.Null;
 
6012
                                }
 
6013
 
 
6014
                                type = new TypeExpression (variable.Variable.Type, variable.Variable.Location);
 
6015
                        } else {
 
6016
                                throw new NotImplementedException ("Unexpected array initializer context");
 
6017
                        }
 
6018
 
 
6019
                        return new ArrayCreation (type, this).Resolve (rc);
 
6020
                }
 
6021
 
 
6022
                public override void Emit (EmitContext ec)
 
6023
                {
 
6024
                        throw new InternalErrorException ("Missing Resolve call");
 
6025
                }
 
6026
                
 
6027
                public override object Accept (StructuralVisitor visitor)
 
6028
                {
 
6029
                        return visitor.Visit (this);
 
6030
                }
 
6031
        }
 
6032
 
 
6033
        /// <summary>
 
6034
        ///   14.5.10.2: Represents an array creation expression.
 
6035
        /// </summary>
 
6036
        ///
 
6037
        /// <remarks>
 
6038
        ///   There are two possible scenarios here: one is an array creation
 
6039
        ///   expression that specifies the dimensions and optionally the
 
6040
        ///   initialization data and the other which does not need dimensions
 
6041
        ///   specified but where initialization data is mandatory.
 
6042
        /// </remarks>
 
6043
        public class ArrayCreation : Expression
 
6044
        {
 
6045
                FullNamedExpression requested_base_type;
 
6046
                ArrayInitializer initializers;
 
6047
 
 
6048
                //
 
6049
                // The list of Argument types.
 
6050
                // This is used to construct the `newarray' or constructor signature
 
6051
                //
 
6052
                protected List<Expression> arguments;
 
6053
                
 
6054
                protected TypeSpec array_element_type;
 
6055
                int num_arguments = 0;
 
6056
                protected int dimensions;
 
6057
                protected readonly ComposedTypeSpecifier rank;
 
6058
                Expression first_emit;
 
6059
                LocalTemporary first_emit_temp;
 
6060
 
 
6061
                protected List<Expression> array_data;
 
6062
 
 
6063
                Dictionary<int, int> bounds;
 
6064
 
 
6065
                // The number of constants in array initializers
 
6066
                int const_initializers_count;
 
6067
                bool only_constant_initializers;
 
6068
                
 
6069
                public List<Expression> Arguments {
 
6070
                        get { return this.arguments; }
 
6071
                }
 
6072
                
 
6073
                public ComposedTypeSpecifier Rank {
 
6074
                        get { return this.rank; }
 
6075
                }
 
6076
                
 
6077
                public FullNamedExpression NewType {
 
6078
                        get { return this.requested_base_type; }
 
6079
                }
 
6080
                
 
6081
                public ArrayInitializer Initializers {
 
6082
                        get { return this.initializers; }
 
6083
                }
 
6084
                
 
6085
                public ArrayCreation (FullNamedExpression requested_base_type, List<Expression> exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l)
 
6086
                        : this (requested_base_type, rank, initializers, l)
 
6087
                {
 
6088
                        arguments = exprs;
 
6089
                        num_arguments = arguments.Count;
 
6090
                }
 
6091
 
 
6092
                //
 
6093
                // For expressions like int[] foo = new int[] { 1, 2, 3 };
 
6094
                //
 
6095
                public ArrayCreation (FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)
 
6096
                {
 
6097
                        this.requested_base_type = requested_base_type;
 
6098
                        this.rank = rank;
 
6099
                        this.initializers = initializers;
 
6100
                        this.loc = loc;
 
6101
 
 
6102
                        if (rank != null)
 
6103
                                num_arguments = rank.Dimension;
 
6104
                }
 
6105
 
 
6106
                //
 
6107
                // For compiler generated single dimensional arrays only
 
6108
                //
 
6109
                public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc)
 
6110
                        : this (requested_base_type, ComposedTypeSpecifier.SingleDimension, initializers, loc)
 
6111
                {
 
6112
                }
 
6113
 
 
6114
                //
 
6115
                // For expressions like int[] foo = { 1, 2, 3 };
 
6116
                //
 
6117
                public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers)
 
6118
                        : this (requested_base_type, null, initializers, initializers.Location)
 
6119
                {
 
6120
                }
 
6121
 
 
6122
                protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
 
6123
                {
 
6124
                        ec.Report.Error (248, loc, "Cannot create an array with a negative size");
 
6125
                }
 
6126
 
 
6127
                bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds)
 
6128
                {
 
6129
                        if (initializers != null && bounds == null) {
 
6130
                                //
 
6131
                                // We use this to store all the date values in the order in which we
 
6132
                                // will need to store them in the byte blob later
 
6133
                                //
 
6134
                                array_data = new List<Expression> ();
 
6135
                                bounds = new Dictionary<int, int> ();
 
6136
                        }
 
6137
 
 
6138
                        if (specified_dims) { 
 
6139
                                Expression a = arguments [idx];
 
6140
                                a = a.Resolve (ec);
 
6141
                                if (a == null)
 
6142
                                        return false;
 
6143
 
 
6144
                                a = ConvertExpressionToArrayIndex (ec, a);
 
6145
                                if (a == null)
 
6146
                                        return false;
 
6147
 
 
6148
                                arguments[idx] = a;
 
6149
 
 
6150
                                if (initializers != null) {
 
6151
                                        Constant c = a as Constant;
 
6152
                                        if (c == null && a is ArrayIndexCast)
 
6153
                                                c = ((ArrayIndexCast) a).Child as Constant;
 
6154
 
 
6155
                                        if (c == null) {
 
6156
                                                ec.Report.Error (150, a.Location, "A constant value is expected");
 
6157
                                                return false;
 
6158
                                        }
 
6159
 
 
6160
                                        int value;
 
6161
                                        try {
 
6162
                                                value = System.Convert.ToInt32 (c.GetValue ());
 
6163
                                        } catch {
 
6164
                                                ec.Report.Error (150, a.Location, "A constant value is expected");
 
6165
                                                return false;
 
6166
                                        }
 
6167
 
 
6168
                                        // TODO: probe.Count does not fit ulong in
 
6169
                                        if (value != probe.Count) {
 
6170
                                                ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value.ToString ());
 
6171
                                                return false;
 
6172
                                        }
 
6173
 
 
6174
                                        bounds[idx] = value;
 
6175
                                }
 
6176
                        }
 
6177
 
 
6178
                        if (initializers == null)
 
6179
                                return true;
 
6180
 
 
6181
                        for (int i = 0; i < probe.Count; ++i) {
 
6182
                                var o = probe [i];
 
6183
                                if (o is ArrayInitializer) {
 
6184
                                        var sub_probe = o as ArrayInitializer;
 
6185
                                        if (idx + 1 >= dimensions){
 
6186
                                                ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead");
 
6187
                                                return false;
 
6188
                                        }
 
6189
                                        
 
6190
                                        bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1);
 
6191
                                        if (!ret)
 
6192
                                                return false;
 
6193
                                } else if (child_bounds > 1) {
 
6194
                                        ec.Report.Error (846, o.Location, "A nested array initializer was expected");
 
6195
                                } else {
 
6196
                                        Expression element = ResolveArrayElement (ec, o);
 
6197
                                        if (element == null)
 
6198
                                                continue;
 
6199
 
 
6200
                                        // Initializers with the default values can be ignored
 
6201
                                        Constant c = element as Constant;
 
6202
                                        if (c != null) {
 
6203
                                                if (!c.IsDefaultInitializer (array_element_type)) {
 
6204
                                                        ++const_initializers_count;
 
6205
                                                }
 
6206
                                        } else {
 
6207
                                                only_constant_initializers = false;
 
6208
                                        }
 
6209
                                        
 
6210
                                        array_data.Add (element);
 
6211
                                }
 
6212
                        }
 
6213
 
 
6214
                        return true;
 
6215
                }
 
6216
 
 
6217
                public override Expression CreateExpressionTree (ResolveContext ec)
 
6218
                {
 
6219
                        Arguments args;
 
6220
 
 
6221
                        if (array_data == null) {
 
6222
                                args = new Arguments (arguments.Count + 1);
 
6223
                                args.Add (new Argument (new TypeOf (array_element_type, loc)));
 
6224
                                foreach (Expression a in arguments)
 
6225
                                        args.Add (new Argument (a.CreateExpressionTree (ec)));
 
6226
 
 
6227
                                return CreateExpressionFactoryCall (ec, "NewArrayBounds", args);
 
6228
                        }
 
6229
 
 
6230
                        if (dimensions > 1) {
 
6231
                                ec.Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer");
 
6232
                                return null;
 
6233
                        }
 
6234
 
 
6235
                        args = new Arguments (array_data == null ? 1 : array_data.Count + 1);
 
6236
                        args.Add (new Argument (new TypeOf (array_element_type, loc)));
 
6237
                        if (array_data != null) {
 
6238
                                for (int i = 0; i < array_data.Count; ++i) {
 
6239
                                        Expression e = array_data [i];
 
6240
                                        args.Add (new Argument (e.CreateExpressionTree (ec)));
 
6241
                                }
 
6242
                        }
 
6243
 
 
6244
                        return CreateExpressionFactoryCall (ec, "NewArrayInit", args);
 
6245
                }               
 
6246
                
 
6247
                void UpdateIndices (ResolveContext rc)
 
6248
                {
 
6249
                        int i = 0;
 
6250
                        for (var probe = initializers; probe != null;) {
 
6251
                                Expression e = new IntConstant (rc.BuiltinTypes, probe.Count, Location.Null);
 
6252
                                arguments.Add (e);
 
6253
                                bounds[i++] = probe.Count;
 
6254
 
 
6255
                                if (probe.Count > 0 && probe [0] is ArrayInitializer) {
 
6256
                                        probe = (ArrayInitializer) probe[0];
 
6257
                                } else if (dimensions > i) {
 
6258
                                        continue;
 
6259
                                } else {
 
6260
                                        return;
 
6261
                                }
 
6262
                        }
 
6263
                }
 
6264
 
 
6265
                protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element)
 
6266
                {
 
6267
                        element = element.Resolve (ec);
 
6268
                        if (element == null)
 
6269
                                return null;
 
6270
 
 
6271
                        if (element is CompoundAssign.TargetExpression) {
 
6272
                                if (first_emit != null)
 
6273
                                        throw new InternalErrorException ("Can only handle one mutator at a time");
 
6274
                                first_emit = element;
 
6275
                                element = first_emit_temp = new LocalTemporary (element.Type);
 
6276
                        }
 
6277
 
 
6278
                        return Convert.ImplicitConversionRequired (
 
6279
                                ec, element, array_element_type, loc);
 
6280
                }
 
6281
 
 
6282
                protected bool ResolveInitializers (ResolveContext ec)
 
6283
                {
 
6284
                        only_constant_initializers = true;
 
6285
 
 
6286
                        if (arguments != null) {
 
6287
                                bool res = true;
 
6288
                                for (int i = 0; i < arguments.Count; ++i) {
 
6289
                                        res &= CheckIndices (ec, initializers, i, true, dimensions);
 
6290
                                        if (initializers != null)
 
6291
                                                break;
 
6292
                                }
 
6293
 
 
6294
                                return res;
 
6295
                        }
 
6296
 
 
6297
                        arguments = new List<Expression> ();
 
6298
 
 
6299
                        if (!CheckIndices (ec, initializers, 0, false, dimensions))
 
6300
                                return false;
 
6301
                                
 
6302
                        UpdateIndices (ec);
 
6303
                                
 
6304
                        return true;
 
6305
                }
 
6306
 
 
6307
                //
 
6308
                // Resolved the type of the array
 
6309
                //
 
6310
                bool ResolveArrayType (ResolveContext ec)
 
6311
                {
 
6312
                        //
 
6313
                        // Lookup the type
 
6314
                        //
 
6315
                        FullNamedExpression array_type_expr;
 
6316
                        if (num_arguments > 0) {
 
6317
                                array_type_expr = new ComposedCast (requested_base_type, rank);
 
6318
                        } else {
 
6319
                                array_type_expr = requested_base_type;
 
6320
                        }
 
6321
 
 
6322
                        type = array_type_expr.ResolveAsType (ec);
 
6323
                        if (array_type_expr == null)
 
6324
                                return false;
 
6325
 
 
6326
                        var ac = type as ArrayContainer;
 
6327
                        if (ac == null) {
 
6328
                                ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead");
 
6329
                                return false;
 
6330
                        }
 
6331
 
 
6332
                        array_element_type = ac.Element;
 
6333
                        dimensions = ac.Rank;
 
6334
 
 
6335
                        return true;
 
6336
                }
 
6337
 
 
6338
                protected override Expression DoResolve (ResolveContext ec)
 
6339
                {
 
6340
                        if (type != null)
 
6341
                                return this;
 
6342
 
 
6343
                        if (!ResolveArrayType (ec))
 
6344
                                return null;
 
6345
 
 
6346
                        //
 
6347
                        // validate the initializers and fill in any missing bits
 
6348
                        //
 
6349
                        if (!ResolveInitializers (ec))
 
6350
                                return null;
 
6351
 
 
6352
                        eclass = ExprClass.Value;
 
6353
                        return this;
 
6354
                }
 
6355
 
 
6356
                byte [] MakeByteBlob ()
 
6357
                {
 
6358
                        int factor;
 
6359
                        byte [] data;
 
6360
                        byte [] element;
 
6361
                        int count = array_data.Count;
 
6362
 
 
6363
                        TypeSpec element_type = array_element_type;
 
6364
                        if (TypeManager.IsEnumType (element_type))
 
6365
                                element_type = EnumSpec.GetUnderlyingType (element_type);
 
6366
 
 
6367
                        factor = BuiltinTypeSpec.GetSize (element_type);
 
6368
                        if (factor == 0)
 
6369
                                throw new Exception ("unrecognized type in MakeByteBlob: " + element_type);
 
6370
 
 
6371
                        data = new byte [(count * factor + 3) & ~3];
 
6372
                        int idx = 0;
 
6373
 
 
6374
                        for (int i = 0; i < count; ++i) {
 
6375
                                var c = array_data[i] as Constant;
 
6376
                                if (c == null) {
 
6377
                                        idx += factor;
 
6378
                                        continue;
 
6379
                                }
 
6380
 
 
6381
                                object v = c.GetValue ();
 
6382
 
 
6383
                                switch (element_type.BuiltinType) {
 
6384
                                case BuiltinTypeSpec.Type.Long:
 
6385
                                        long lval = (long) v;
 
6386
 
 
6387
                                        for (int j = 0; j < factor; ++j) {
 
6388
                                                data[idx + j] = (byte) (lval & 0xFF);
 
6389
                                                lval = (lval >> 8);
 
6390
                                        }
 
6391
                                        break;
 
6392
                                case BuiltinTypeSpec.Type.ULong:
 
6393
                                        ulong ulval = (ulong) v;
 
6394
 
 
6395
                                        for (int j = 0; j < factor; ++j) {
 
6396
                                                data[idx + j] = (byte) (ulval & 0xFF);
 
6397
                                                ulval = (ulval >> 8);
 
6398
                                        }
 
6399
                                        break;
 
6400
                                case BuiltinTypeSpec.Type.Float:
 
6401
                                        element = BitConverter.GetBytes ((float) v);
 
6402
 
 
6403
                                        for (int j = 0; j < factor; ++j)
 
6404
                                                data[idx + j] = element[j];
 
6405
                                        if (!BitConverter.IsLittleEndian)
 
6406
                                                System.Array.Reverse (data, idx, 4);
 
6407
                                        break;
 
6408
                                case BuiltinTypeSpec.Type.Double:
 
6409
                                        element = BitConverter.GetBytes ((double) v);
 
6410
 
 
6411
                                        for (int j = 0; j < factor; ++j)
 
6412
                                                data[idx + j] = element[j];
 
6413
 
 
6414
                                        // FIXME: Handle the ARM float format.
 
6415
                                        if (!BitConverter.IsLittleEndian)
 
6416
                                                System.Array.Reverse (data, idx, 8);
 
6417
                                        break;
 
6418
                                case BuiltinTypeSpec.Type.Char:
 
6419
                                        int chval = (int) ((char) v);
 
6420
 
 
6421
                                        data[idx] = (byte) (chval & 0xff);
 
6422
                                        data[idx + 1] = (byte) (chval >> 8);
 
6423
                                        break;
 
6424
                                case BuiltinTypeSpec.Type.Short:
 
6425
                                        int sval = (int) ((short) v);
 
6426
 
 
6427
                                        data[idx] = (byte) (sval & 0xff);
 
6428
                                        data[idx + 1] = (byte) (sval >> 8);
 
6429
                                        break;
 
6430
                                case BuiltinTypeSpec.Type.UShort:
 
6431
                                        int usval = (int) ((ushort) v);
 
6432
 
 
6433
                                        data[idx] = (byte) (usval & 0xff);
 
6434
                                        data[idx + 1] = (byte) (usval >> 8);
 
6435
                                        break;
 
6436
                                case BuiltinTypeSpec.Type.Int:
 
6437
                                        int val = (int) v;
 
6438
 
 
6439
                                        data[idx] = (byte) (val & 0xff);
 
6440
                                        data[idx + 1] = (byte) ((val >> 8) & 0xff);
 
6441
                                        data[idx + 2] = (byte) ((val >> 16) & 0xff);
 
6442
                                        data[idx + 3] = (byte) (val >> 24);
 
6443
                                        break;
 
6444
                                case BuiltinTypeSpec.Type.UInt:
 
6445
                                        uint uval = (uint) v;
 
6446
 
 
6447
                                        data[idx] = (byte) (uval & 0xff);
 
6448
                                        data[idx + 1] = (byte) ((uval >> 8) & 0xff);
 
6449
                                        data[idx + 2] = (byte) ((uval >> 16) & 0xff);
 
6450
                                        data[idx + 3] = (byte) (uval >> 24);
 
6451
                                        break;
 
6452
                                case BuiltinTypeSpec.Type.SByte:
 
6453
                                        data[idx] = (byte) (sbyte) v;
 
6454
                                        break;
 
6455
                                case BuiltinTypeSpec.Type.Byte:
 
6456
                                        data[idx] = (byte) v;
 
6457
                                        break;
 
6458
                                case BuiltinTypeSpec.Type.Bool:
 
6459
                                        data[idx] = (byte) ((bool) v ? 1 : 0);
 
6460
                                        break;
 
6461
                                case BuiltinTypeSpec.Type.Decimal:
 
6462
                                        int[] bits = Decimal.GetBits ((decimal) v);
 
6463
                                        int p = idx;
 
6464
 
 
6465
                                        // FIXME: For some reason, this doesn't work on the MS runtime.
 
6466
                                        int[] nbits = new int[4];
 
6467
                                        nbits[0] = bits[3];
 
6468
                                        nbits[1] = bits[2];
 
6469
                                        nbits[2] = bits[0];
 
6470
                                        nbits[3] = bits[1];
 
6471
 
 
6472
                                        for (int j = 0; j < 4; j++) {
 
6473
                                                data[p++] = (byte) (nbits[j] & 0xff);
 
6474
                                                data[p++] = (byte) ((nbits[j] >> 8) & 0xff);
 
6475
                                                data[p++] = (byte) ((nbits[j] >> 16) & 0xff);
 
6476
                                                data[p++] = (byte) (nbits[j] >> 24);
 
6477
                                        }
 
6478
                                        break;
 
6479
                                default:
 
6480
                                        throw new Exception ("Unrecognized type in MakeByteBlob: " + element_type);
 
6481
                                }
 
6482
 
 
6483
                                idx += factor;
 
6484
                        }
 
6485
 
 
6486
                        return data;
 
6487
                }
 
6488
 
 
6489
#if NET_4_0
 
6490
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
6491
                {
 
6492
#if STATIC
 
6493
                        return base.MakeExpression (ctx);
 
6494
#else
 
6495
                        var initializers = new SLE.Expression [array_data.Count];
 
6496
                        for (var i = 0; i < initializers.Length; i++) {
 
6497
                                if (array_data [i] == null)
 
6498
                                        initializers [i] = SLE.Expression.Default (array_element_type.GetMetaInfo ());
 
6499
                                else
 
6500
                                        initializers [i] = array_data [i].MakeExpression (ctx);
 
6501
                        }
 
6502
 
 
6503
                        return SLE.Expression.NewArrayInit (array_element_type.GetMetaInfo (), initializers);
 
6504
#endif
 
6505
                }
 
6506
#endif
 
6507
#if STATIC
 
6508
                //
 
6509
                // Emits the initializers for the array
 
6510
                //
 
6511
                void EmitStaticInitializers (EmitContext ec)
 
6512
                {
 
6513
                        var m = ec.Module.PredefinedMembers.RuntimeHelpersInitializeArray.Resolve (loc);
 
6514
                        if (m == null)
 
6515
                                return;
 
6516
 
 
6517
                        //
 
6518
                        // First, the static data
 
6519
                        //
 
6520
                        byte [] data = MakeByteBlob ();
 
6521
                        var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (data, loc);
 
6522
 
 
6523
                        ec.Emit (OpCodes.Dup);
 
6524
                        ec.Emit (OpCodes.Ldtoken, fb);
 
6525
                        ec.Emit (OpCodes.Call, m);
 
6526
                }
 
6527
#endif
 
6528
 
 
6529
                //
 
6530
                // Emits pieces of the array that can not be computed at compile
 
6531
                // time (variables and string locations).
 
6532
                //
 
6533
                // This always expect the top value on the stack to be the array
 
6534
                //
 
6535
                void EmitDynamicInitializers (EmitContext ec, bool emitConstants)
 
6536
                {
 
6537
                        int dims = bounds.Count;
 
6538
                        var current_pos = new int [dims];
 
6539
 
 
6540
                        for (int i = 0; i < array_data.Count; i++){
 
6541
 
 
6542
                                Expression e = array_data [i];
 
6543
                                var c = e as Constant;
 
6544
 
 
6545
                                // Constant can be initialized via StaticInitializer
 
6546
                                if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) {
 
6547
                                        TypeSpec etype = e.Type;
 
6548
 
 
6549
                                        ec.Emit (OpCodes.Dup);
 
6550
 
 
6551
                                        for (int idx = 0; idx < dims; idx++) 
 
6552
                                                ec.EmitInt (current_pos [idx]);
 
6553
 
 
6554
                                        //
 
6555
                                        // If we are dealing with a struct, get the
 
6556
                                        // address of it, so we can store it.
 
6557
                                        //
 
6558
                                        if (dims == 1 && etype.IsStruct) {
 
6559
                                                switch (etype.BuiltinType) {
 
6560
                                                case BuiltinTypeSpec.Type.Byte:
 
6561
                                                case BuiltinTypeSpec.Type.SByte:
 
6562
                                                case BuiltinTypeSpec.Type.Bool:
 
6563
                                                case BuiltinTypeSpec.Type.Short:
 
6564
                                                case BuiltinTypeSpec.Type.UShort:
 
6565
                                                case BuiltinTypeSpec.Type.Char:
 
6566
                                                case BuiltinTypeSpec.Type.Int:
 
6567
                                                case BuiltinTypeSpec.Type.UInt:
 
6568
                                                case BuiltinTypeSpec.Type.Long:
 
6569
                                                case BuiltinTypeSpec.Type.ULong:
 
6570
                                                case BuiltinTypeSpec.Type.Float:
 
6571
                                                case BuiltinTypeSpec.Type.Double:
 
6572
                                                        break;
 
6573
                                                default:
 
6574
                                                        ec.Emit (OpCodes.Ldelema, etype);
 
6575
                                                        break;
 
6576
                                                }
 
6577
                                        }
 
6578
 
 
6579
                                        e.Emit (ec);
 
6580
 
 
6581
                                        ec.EmitArrayStore ((ArrayContainer) type);
 
6582
                                }
 
6583
                                
 
6584
                                //
 
6585
                                // Advance counter
 
6586
                                //
 
6587
                                for (int j = dims - 1; j >= 0; j--){
 
6588
                                        current_pos [j]++;
 
6589
                                        if (current_pos [j] < bounds [j])
 
6590
                                                break;
 
6591
                                        current_pos [j] = 0;
 
6592
                                }
 
6593
                        }
 
6594
                }
 
6595
 
 
6596
                public override void Emit (EmitContext ec)
 
6597
                {
 
6598
                        if (first_emit != null) {
 
6599
                                first_emit.Emit (ec);
 
6600
                                first_emit_temp.Store (ec);
 
6601
                        }
 
6602
 
 
6603
                        foreach (Expression e in arguments)
 
6604
                                e.Emit (ec);
 
6605
 
 
6606
                        ec.EmitArrayNew ((ArrayContainer) type);
 
6607
                        
 
6608
                        if (initializers == null)
 
6609
                                return;
 
6610
 
 
6611
#if STATIC
 
6612
                        // Emit static initializer for arrays which have contain more than 2 items and
 
6613
                        // the static initializer will initialize at least 25% of array values or there
 
6614
                        // is more than 10 items to be initialized
 
6615
                        // NOTE: const_initializers_count does not contain default constant values.
 
6616
                        if (const_initializers_count > 2 && (array_data.Count > 10 || const_initializers_count * 4 > (array_data.Count)) &&
 
6617
                                (BuiltinTypeSpec.IsPrimitiveType (array_element_type) || array_element_type.IsEnum)) {
 
6618
                                EmitStaticInitializers (ec);
 
6619
 
 
6620
                                if (!only_constant_initializers)
 
6621
                                        EmitDynamicInitializers (ec, false);
 
6622
                        } else
 
6623
#endif
 
6624
                        {
 
6625
                                EmitDynamicInitializers (ec, true);
 
6626
                        }
 
6627
 
 
6628
                        if (first_emit_temp != null)
 
6629
                                first_emit_temp.Release (ec);
 
6630
                }
 
6631
 
 
6632
                public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
 
6633
                {
 
6634
                        // no multi dimensional or jagged arrays
 
6635
                        if (arguments.Count != 1 || array_element_type.IsArray) {
 
6636
                                base.EncodeAttributeValue (rc, enc, targetType);
 
6637
                                return;
 
6638
                        }
 
6639
 
 
6640
                        // No array covariance, except for array -> object
 
6641
                        if (type != targetType) {
 
6642
                                if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) {
 
6643
                                        base.EncodeAttributeValue (rc, enc, targetType);
 
6644
                                        return;
 
6645
                                }
 
6646
 
 
6647
                                if (enc.Encode (type) == AttributeEncoder.EncodedTypeProperties.DynamicType) {
 
6648
                                        Attribute.Error_AttributeArgumentIsDynamic (rc, loc);
 
6649
                                        return;
 
6650
                                }
 
6651
                        }
 
6652
 
 
6653
                        // Single dimensional array of 0 size
 
6654
                        if (array_data == null) {
 
6655
                                IntConstant ic = arguments[0] as IntConstant;
 
6656
                                if (ic == null || !ic.IsDefaultValue) {
 
6657
                                        base.EncodeAttributeValue (rc, enc, targetType);
 
6658
                                } else {
 
6659
                                        enc.Encode (0);
 
6660
                                }
 
6661
 
 
6662
                                return;
 
6663
                        }
 
6664
 
 
6665
                        enc.Encode (array_data.Count);
 
6666
                        foreach (var element in array_data) {
 
6667
                                element.EncodeAttributeValue (rc, enc, array_element_type);
 
6668
                        }
 
6669
                }
 
6670
                
 
6671
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
6672
                {
 
6673
                        ArrayCreation target = (ArrayCreation) t;
 
6674
 
 
6675
                        if (requested_base_type != null)
 
6676
                                target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx);
 
6677
 
 
6678
                        if (arguments != null){
 
6679
                                target.arguments = new List<Expression> (arguments.Count);
 
6680
                                foreach (Expression e in arguments)
 
6681
                                        target.arguments.Add (e.Clone (clonectx));
 
6682
                        }
 
6683
 
 
6684
                        if (initializers != null)
 
6685
                                target.initializers = (ArrayInitializer) initializers.Clone (clonectx);
 
6686
                }
 
6687
                
 
6688
                public override object Accept (StructuralVisitor visitor)
 
6689
                {
 
6690
                        return visitor.Visit (this);
 
6691
                }
 
6692
        }
 
6693
        
 
6694
        //
 
6695
        // Represents an implicitly typed array epxression
 
6696
        //
 
6697
        class ImplicitlyTypedArrayCreation : ArrayCreation
 
6698
        {
 
6699
                sealed class InferenceContext : TypeInferenceContext
 
6700
                {
 
6701
                        class ExpressionBoundInfo : BoundInfo
 
6702
                        {
 
6703
                                readonly Expression expr;
 
6704
 
 
6705
                                public ExpressionBoundInfo (Expression expr)
 
6706
                                        : base (expr.Type, BoundKind.Lower)
 
6707
                                {
 
6708
                                        this.expr = expr;
 
6709
                                }
 
6710
 
 
6711
                                public override bool Equals (BoundInfo other)
 
6712
                                {
 
6713
                                        // We are using expression not type for conversion check
 
6714
                                        // no optimization based on types is possible
 
6715
                                        return false;
 
6716
                                }
 
6717
 
 
6718
                                public override Expression GetTypeExpression ()
 
6719
                                {
 
6720
                                        return expr;
 
6721
                                }
 
6722
                        }
 
6723
 
 
6724
                        public void AddExpression (Expression expr)
 
6725
                        {
 
6726
                                AddToBounds (new ExpressionBoundInfo (expr), 0);
 
6727
                        }
 
6728
                }
 
6729
 
 
6730
                InferenceContext best_type_inference;
 
6731
 
 
6732
                public ImplicitlyTypedArrayCreation (ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc)
 
6733
                        : base (null, rank, initializers, loc)
 
6734
                {                       
 
6735
                }
 
6736
 
 
6737
                public ImplicitlyTypedArrayCreation (ArrayInitializer initializers, Location loc)
 
6738
                        : base (null, initializers, loc)
 
6739
                {
 
6740
                }
 
6741
 
 
6742
                protected override Expression DoResolve (ResolveContext ec)
 
6743
                {
 
6744
                        if (type != null)
 
6745
                                return this;
 
6746
 
 
6747
                        dimensions = rank.Dimension;
 
6748
 
 
6749
                        best_type_inference = new InferenceContext ();
 
6750
 
 
6751
                        if (!ResolveInitializers (ec))
 
6752
                                return null;
 
6753
 
 
6754
                        best_type_inference.FixAllTypes (ec);
 
6755
                        array_element_type = best_type_inference.InferredTypeArguments[0];
 
6756
                        best_type_inference = null;
 
6757
 
 
6758
                        if (array_element_type == null || array_element_type == InternalType.MethodGroup || array_element_type == InternalType.AnonymousMethod ||
 
6759
                                arguments.Count != rank.Dimension) {
 
6760
                                ec.Report.Error (826, loc,
 
6761
                                        "The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly");
 
6762
                                return null;
 
6763
                        }
 
6764
 
 
6765
                        //
 
6766
                        // At this point we found common base type for all initializer elements
 
6767
                        // but we have to be sure that all static initializer elements are of
 
6768
                        // same type
 
6769
                        //
 
6770
                        UnifyInitializerElement (ec);
 
6771
 
 
6772
                        type = ArrayContainer.MakeType (ec.Module, array_element_type, dimensions);
 
6773
                        eclass = ExprClass.Value;
 
6774
                        return this;
 
6775
                }
 
6776
 
 
6777
                //
 
6778
                // Converts static initializer only
 
6779
                //
 
6780
                void UnifyInitializerElement (ResolveContext ec)
 
6781
                {
 
6782
                        for (int i = 0; i < array_data.Count; ++i) {
 
6783
                                Expression e = array_data[i];
 
6784
                                if (e != null)
 
6785
                                        array_data [i] = Convert.ImplicitConversion (ec, e, array_element_type, Location.Null);
 
6786
                        }
 
6787
                }
 
6788
 
 
6789
                protected override Expression ResolveArrayElement (ResolveContext ec, Expression element)
 
6790
                {
 
6791
                        element = element.Resolve (ec);
 
6792
                        if (element != null)
 
6793
                                best_type_inference.AddExpression (element);
 
6794
 
 
6795
                        return element;
 
6796
                }
 
6797
        }       
 
6798
        
 
6799
        sealed class CompilerGeneratedThis : This
 
6800
        {
 
6801
                public CompilerGeneratedThis (TypeSpec type, Location loc)
 
6802
                        : base (loc)
 
6803
                {
 
6804
                        this.type = type;
 
6805
                        eclass = ExprClass.Variable;
 
6806
                }
 
6807
 
 
6808
                protected override Expression DoResolve (ResolveContext ec)
 
6809
                {
 
6810
                        return this;
 
6811
                }
 
6812
 
 
6813
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
 
6814
                {
 
6815
                        return null;
 
6816
                }
 
6817
        }
 
6818
        
 
6819
        /// <summary>
 
6820
        ///   Represents the `this' construct
 
6821
        /// </summary>
 
6822
 
 
6823
        public class This : VariableReference
 
6824
        {
 
6825
                sealed class ThisVariable : ILocalVariable
 
6826
                {
 
6827
                        public static readonly ILocalVariable Instance = new ThisVariable ();
 
6828
 
 
6829
                        public void Emit (EmitContext ec)
 
6830
                        {
 
6831
                                ec.Emit (OpCodes.Ldarg_0);
 
6832
                        }
 
6833
 
 
6834
                        public void EmitAssign (EmitContext ec)
 
6835
                        {
 
6836
                                throw new InvalidOperationException ();
 
6837
                        }
 
6838
 
 
6839
                        public void EmitAddressOf (EmitContext ec)
 
6840
                        {
 
6841
                                ec.Emit (OpCodes.Ldarg_0);
 
6842
                        }
 
6843
                }
 
6844
 
 
6845
                VariableInfo variable_info;
 
6846
 
 
6847
                public This (Location loc)
 
6848
                {
 
6849
                        this.loc = loc;
 
6850
                }
 
6851
 
 
6852
                #region Properties
 
6853
 
 
6854
                public override string Name {
 
6855
                        get { return "this"; }
 
6856
                }
 
6857
 
 
6858
                public override bool IsLockedByStatement {
 
6859
                        get {
 
6860
                                return false;
 
6861
                        }
 
6862
                        set {
 
6863
                        }
 
6864
                }
 
6865
 
 
6866
                public override bool IsRef {
 
6867
                        get { return type.IsStruct; }
 
6868
                }
 
6869
 
 
6870
                protected override ILocalVariable Variable {
 
6871
                        get { return ThisVariable.Instance; }
 
6872
                }
 
6873
 
 
6874
                public override VariableInfo VariableInfo {
 
6875
                        get { return variable_info; }
 
6876
                }
 
6877
 
 
6878
                public override bool IsFixed {
 
6879
                        get { return false; }
 
6880
                }
 
6881
 
 
6882
                #endregion
 
6883
 
 
6884
                public void CheckStructThisDefiniteAssignment (ResolveContext rc)
 
6885
                {
 
6886
                        if (variable_info != null && !variable_info.IsAssigned (rc)) {
 
6887
                                rc.Report.Error (188, loc,
 
6888
                                        "The `this' object cannot be used before all of its fields are assigned to");
 
6889
                        }
 
6890
                }
 
6891
 
 
6892
                protected virtual void Error_ThisNotAvailable (ResolveContext ec)
 
6893
                {
 
6894
                        if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) {
 
6895
                                ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer");
 
6896
                        } else if (ec.CurrentAnonymousMethod != null) {
 
6897
                                ec.Report.Error (1673, loc,
 
6898
                                        "Anonymous methods inside structs cannot access instance members of `this'. " +
 
6899
                                        "Consider copying `this' to a local variable outside the anonymous method and using the local instead");
 
6900
                        } else {
 
6901
                                ec.Report.Error (27, loc, "Keyword `this' is not available in the current context");
 
6902
                        }
 
6903
                }
 
6904
 
 
6905
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
 
6906
                {
 
6907
                        if (ae == null)
 
6908
                                return null;
 
6909
 
 
6910
                        AnonymousMethodStorey storey = ae.Storey;
 
6911
                        while (storey != null) {
 
6912
                                AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey;
 
6913
                                if (temp == null)
 
6914
                                        return storey.HoistedThis;
 
6915
 
 
6916
                                storey = temp;
 
6917
                        }
 
6918
 
 
6919
                        return null;
 
6920
                }
 
6921
 
 
6922
                public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous)
 
6923
                {
 
6924
                        if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope))
 
6925
                                return false;
 
6926
 
 
6927
                        if (ignoreAnonymous || ec.CurrentAnonymousMethod == null)
 
6928
                                return true;
 
6929
 
 
6930
                        if (ec.CurrentType.IsStruct && ec.CurrentIterator == null)
 
6931
                                return false;
 
6932
 
 
6933
                        return true;
 
6934
                }
 
6935
 
 
6936
                public virtual void ResolveBase (ResolveContext ec)
 
6937
                {
 
6938
                        eclass = ExprClass.Variable;
 
6939
                        type = ec.CurrentType;
 
6940
 
 
6941
                        if (!IsThisAvailable (ec, false)) {
 
6942
                                Error_ThisNotAvailable (ec);
 
6943
                                return;
 
6944
                        }
 
6945
 
 
6946
                        var block = ec.CurrentBlock;
 
6947
                        if (block != null) {
 
6948
                                if (block.ParametersBlock.TopBlock.ThisVariable != null)
 
6949
                                        variable_info = block.ParametersBlock.TopBlock.ThisVariable.VariableInfo;
 
6950
 
 
6951
                                AnonymousExpression am = ec.CurrentAnonymousMethod;
 
6952
                                if (am != null && ec.IsVariableCapturingRequired) {
 
6953
                                        am.SetHasThisAccess ();
 
6954
                                }
 
6955
                        }
 
6956
                }
 
6957
 
 
6958
                public override Expression CreateExpressionTree (ResolveContext ec)
 
6959
                {
 
6960
                        Arguments args = new Arguments (1);
 
6961
                        args.Add (new Argument (this));
 
6962
                        
 
6963
                        // Use typeless constant for ldarg.0 to save some
 
6964
                        // space and avoid problems with anonymous stories
 
6965
                        return CreateExpressionFactoryCall (ec, "Constant", args);
 
6966
                }
 
6967
                
 
6968
                protected override Expression DoResolve (ResolveContext ec)
 
6969
                {
 
6970
                        ResolveBase (ec);
 
6971
 
 
6972
                        if (variable_info != null && type.IsStruct) {
 
6973
                                CheckStructThisDefiniteAssignment (ec);
 
6974
                        }
 
6975
 
 
6976
                        return this;
 
6977
                }
 
6978
 
 
6979
                override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
6980
                {
 
6981
                        ResolveBase (ec);
 
6982
 
 
6983
                        if (variable_info != null)
 
6984
                                variable_info.SetAssigned (ec);
 
6985
 
 
6986
                        if (type.IsClass){
 
6987
                                if (right_side == EmptyExpression.UnaryAddress)
 
6988
                                        ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
 
6989
                                else if (right_side == EmptyExpression.OutAccess)
 
6990
                                        ec.Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only");
 
6991
                                else
 
6992
                                        ec.Report.Error (1604, loc, "Cannot assign to `this' because it is read-only");
 
6993
                        }
 
6994
 
 
6995
                        return this;
 
6996
                }
 
6997
 
 
6998
                public override int GetHashCode()
 
6999
                {
 
7000
                        throw new NotImplementedException ();
 
7001
                }
 
7002
 
 
7003
                public override bool Equals (object obj)
 
7004
                {
 
7005
                        This t = obj as This;
 
7006
                        if (t == null)
 
7007
                                return false;
 
7008
 
 
7009
                        return true;
 
7010
                }
 
7011
 
 
7012
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
7013
                {
 
7014
                        // Nothing
 
7015
                }
 
7016
 
 
7017
                public override void SetHasAddressTaken ()
 
7018
                {
 
7019
                        // Nothing
 
7020
                }
 
7021
                
 
7022
                public override object Accept (StructuralVisitor visitor)
 
7023
                {
 
7024
                        return visitor.Visit (this);
 
7025
                }
 
7026
        }
 
7027
 
 
7028
        /// <summary>
 
7029
        ///   Represents the `__arglist' construct
 
7030
        /// </summary>
 
7031
        public class ArglistAccess : Expression
 
7032
        {
 
7033
                public ArglistAccess (Location loc)
 
7034
                {
 
7035
                        this.loc = loc;
 
7036
                }
 
7037
 
 
7038
                public override Expression CreateExpressionTree (ResolveContext ec)
 
7039
                {
 
7040
                        throw new NotSupportedException ("ET");
 
7041
                }
 
7042
 
 
7043
                protected override Expression DoResolve (ResolveContext ec)
 
7044
                {
 
7045
                        eclass = ExprClass.Variable;
 
7046
                        type = ec.Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
 
7047
 
 
7048
                        if (ec.HasSet (ResolveContext.Options.FieldInitializerScope) || !ec.CurrentBlock.ParametersBlock.Parameters.HasArglist) {
 
7049
                                ec.Report.Error (190, loc,
 
7050
                                        "The __arglist construct is valid only within a variable argument method");
 
7051
                        }
 
7052
 
 
7053
                        return this;
 
7054
                }
 
7055
 
 
7056
                public override void Emit (EmitContext ec)
 
7057
                {
 
7058
                        ec.Emit (OpCodes.Arglist);
 
7059
                }
 
7060
 
 
7061
                protected override void CloneTo (CloneContext clonectx, Expression target)
 
7062
                {
 
7063
                        // nothing.
 
7064
                }
 
7065
                public override object Accept (StructuralVisitor visitor)
 
7066
                {
 
7067
                        return visitor.Visit (this);
 
7068
                }
 
7069
        }
 
7070
 
 
7071
        /// <summary>
 
7072
        ///   Represents the `__arglist (....)' construct
 
7073
        /// </summary>
 
7074
        public class Arglist : Expression
 
7075
        {
 
7076
                public Arguments Arguments { get; private set; }
 
7077
                
 
7078
                public Arglist (Location loc)
 
7079
                        : this (null, loc)
 
7080
                {
 
7081
                }
 
7082
 
 
7083
                public Arglist (Arguments args, Location l)
 
7084
                {
 
7085
                        Arguments = args;
 
7086
                        loc = l;
 
7087
                }
 
7088
 
 
7089
                public MetaType[] ArgumentTypes {
 
7090
                    get {
 
7091
                                if (Arguments == null)
 
7092
                                        return MetaType.EmptyTypes;
 
7093
 
 
7094
                                var retval = new MetaType[Arguments.Count];
 
7095
                        for (int i = 0; i < retval.Length; i++)
 
7096
                                        retval[i] = Arguments[i].Expr.Type.GetMetaInfo ();
 
7097
 
 
7098
                        return retval;
 
7099
                    }
 
7100
                }
 
7101
                
 
7102
                public override Expression CreateExpressionTree (ResolveContext ec)
 
7103
                {
 
7104
                        ec.Report.Error (1952, loc, "An expression tree cannot contain a method with variable arguments");
 
7105
                        return null;
 
7106
                }
 
7107
 
 
7108
                protected override Expression DoResolve (ResolveContext ec)
 
7109
                {
 
7110
                        eclass = ExprClass.Variable;
 
7111
                        type = InternalType.Arglist;
 
7112
                        if (Arguments != null) {
 
7113
                                bool dynamic;   // Can be ignored as there is always only 1 overload
 
7114
                                Arguments.Resolve (ec, out dynamic);
 
7115
                        }
 
7116
 
 
7117
                        return this;
 
7118
                }
 
7119
 
 
7120
                public override void Emit (EmitContext ec)
 
7121
                {
 
7122
                        if (Arguments != null)
 
7123
                                Arguments.Emit (ec);
 
7124
                }
 
7125
 
 
7126
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
7127
                {
 
7128
                        Arglist target = (Arglist) t;
 
7129
 
 
7130
                        if (Arguments != null)
 
7131
                                target.Arguments = Arguments.Clone (clonectx);
 
7132
                }
 
7133
                public override object Accept (StructuralVisitor visitor)
 
7134
                {
 
7135
                        return visitor.Visit (this);
 
7136
                }
 
7137
        }
 
7138
 
 
7139
        public class RefValueExpr : ShimExpression
 
7140
        {
 
7141
                FullNamedExpression texpr;
 
7142
 
 
7143
                public RefValueExpr (Expression expr, FullNamedExpression texpr, Location loc)
 
7144
                        : base (expr)
 
7145
                {
 
7146
                        this.texpr = texpr;
 
7147
                        this.loc = loc;
 
7148
                }
 
7149
 
 
7150
                protected override Expression DoResolve (ResolveContext rc)
 
7151
                {
 
7152
                        expr = expr.Resolve (rc);
 
7153
                        type = texpr.ResolveAsType (rc);
 
7154
                        if (expr == null || type == null)
 
7155
                                return null;
 
7156
 
 
7157
                        expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc);
 
7158
                        eclass = ExprClass.Value;
 
7159
                        return this;
 
7160
                }
 
7161
 
 
7162
                public override void Emit (EmitContext ec)
 
7163
                {
 
7164
                        expr.Emit (ec);
 
7165
                        ec.Emit (OpCodes.Refanyval, type);
 
7166
                        ec.EmitLoadFromPtr (type);
 
7167
                }
 
7168
                
 
7169
                public override object Accept (StructuralVisitor visitor)
 
7170
                {
 
7171
                        return visitor.Visit (this);
 
7172
                }
 
7173
        }
 
7174
 
 
7175
        public class RefTypeExpr : ShimExpression
 
7176
        {
 
7177
                public RefTypeExpr (Expression expr, Location loc)
 
7178
                        : base (expr)
 
7179
                {
 
7180
                        this.loc = loc;
 
7181
                }
 
7182
 
 
7183
                protected override Expression DoResolve (ResolveContext rc)
 
7184
                {
 
7185
                        expr = expr.Resolve (rc);
 
7186
                        if (expr == null)
 
7187
                                return null;
 
7188
 
 
7189
                        expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc);
 
7190
                        if (expr == null)
 
7191
                                return null;
 
7192
 
 
7193
                        type = rc.BuiltinTypes.Type;
 
7194
                        eclass = ExprClass.Value;
 
7195
                        return this;
 
7196
                }
 
7197
 
 
7198
                public override void Emit (EmitContext ec)
 
7199
                {
 
7200
                        expr.Emit (ec);
 
7201
                        ec.Emit (OpCodes.Refanytype);
 
7202
                        var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc);
 
7203
                        if (m != null)
 
7204
                                ec.Emit (OpCodes.Call, m);
 
7205
                }
 
7206
                
 
7207
                public override object Accept (StructuralVisitor visitor)
 
7208
                {
 
7209
                        return visitor.Visit (this);
 
7210
                }
 
7211
        }
 
7212
 
 
7213
        public class MakeRefExpr : ShimExpression
 
7214
        {
 
7215
                public MakeRefExpr (Expression expr, Location loc)
 
7216
                        : base (expr)
 
7217
                {
 
7218
                        this.loc = loc;
 
7219
                }
 
7220
 
 
7221
                protected override Expression DoResolve (ResolveContext rc)
 
7222
                {
 
7223
                        expr = expr.ResolveLValue (rc, EmptyExpression.LValueMemberAccess);
 
7224
                        type = rc.Module.PredefinedTypes.TypedReference.Resolve ();
 
7225
                        eclass = ExprClass.Value;
 
7226
                        return this;
 
7227
                }
 
7228
 
 
7229
                public override void Emit (EmitContext ec)
 
7230
                {
 
7231
                        ((IMemoryLocation) expr).AddressOf (ec, AddressOp.Load);
 
7232
                        ec.Emit (OpCodes.Mkrefany, expr.Type);
 
7233
                }
 
7234
                
 
7235
                public override object Accept (StructuralVisitor visitor)
 
7236
                {
 
7237
                        return visitor.Visit (this);
 
7238
                }
 
7239
        }
 
7240
 
 
7241
        /// <summary>
 
7242
        ///   Implements the typeof operator
 
7243
        /// </summary>
 
7244
        public class TypeOf : Expression {
 
7245
                FullNamedExpression QueriedType;
 
7246
                TypeSpec typearg;
 
7247
 
 
7248
                public TypeOf (FullNamedExpression queried_type, Location l)
 
7249
                {
 
7250
                        QueriedType = queried_type;
 
7251
                        loc = l;
 
7252
                }
 
7253
 
 
7254
                //
 
7255
                // Use this constructor for any compiler generated typeof expression
 
7256
                //
 
7257
                public TypeOf (TypeSpec type, Location loc)
 
7258
                {
 
7259
                        this.typearg = type;
 
7260
                        this.loc = loc;
 
7261
                }
 
7262
 
 
7263
                #region Properties
 
7264
                public TypeSpec TypeArgument {
 
7265
                        get {
 
7266
                                return typearg;
 
7267
                        }
 
7268
                }
 
7269
 
 
7270
                public FullNamedExpression TypeExpression {
 
7271
                        get {
 
7272
                                return QueriedType;
 
7273
                        }
 
7274
                }
 
7275
 
 
7276
                #endregion
 
7277
 
 
7278
                public override Expression CreateExpressionTree (ResolveContext ec)
 
7279
                {
 
7280
                        Arguments args = new Arguments (2);
 
7281
                        args.Add (new Argument (this));
 
7282
                        args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
 
7283
                        return CreateExpressionFactoryCall (ec, "Constant", args);
 
7284
                }
 
7285
 
 
7286
                protected override Expression DoResolve (ResolveContext ec)
 
7287
                {
 
7288
                        if (eclass != ExprClass.Unresolved)
 
7289
                                return this;
 
7290
 
 
7291
                        if (typearg == null) {
 
7292
                                //
 
7293
                                // Pointer types are allowed without explicit unsafe, they are just tokens
 
7294
                                //
 
7295
                                using (ec.Set (ResolveContext.Options.UnsafeScope)) {
 
7296
                                        typearg = QueriedType.ResolveAsType (ec);
 
7297
                                }
 
7298
 
 
7299
                                if (typearg == null)
 
7300
                                        return null;
 
7301
 
 
7302
                                if (typearg.Kind == MemberKind.Void && !(QueriedType is TypeExpression)) {
 
7303
                                        ec.Report.Error (673, loc, "System.Void cannot be used from C#. Use typeof (void) to get the void type object");
 
7304
                                } else if (typearg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
7305
                                        ec.Report.Error (1962, QueriedType.Location,
 
7306
                                                "The typeof operator cannot be used on the dynamic type");
 
7307
                                }
 
7308
                        }
 
7309
 
 
7310
                        type = ec.BuiltinTypes.Type;
 
7311
 
 
7312
                        // Even though what is returned is a type object, it's treated as a value by the compiler.
 
7313
                        // In particular, 'typeof (Foo).X' is something totally different from 'Foo.X'.
 
7314
                        eclass = ExprClass.Value;
 
7315
                        return this;
 
7316
                }
 
7317
 
 
7318
                static bool ContainsDynamicType (TypeSpec type)
 
7319
                {
 
7320
                        if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
7321
                                return true;
 
7322
 
 
7323
                        var element_container = type as ElementTypeSpec;
 
7324
                        if (element_container != null)
 
7325
                                return ContainsDynamicType (element_container.Element);
 
7326
 
 
7327
                        foreach (var t in type.TypeArguments) {
 
7328
                                if (ContainsDynamicType (t)) {
 
7329
                                        return true;
 
7330
                                }
 
7331
                        }
 
7332
 
 
7333
                        return false;
 
7334
                }
 
7335
 
 
7336
                public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
 
7337
                {
 
7338
                        // Target type is not System.Type therefore must be object
 
7339
                        // and we need to use different encoding sequence
 
7340
                        if (targetType != type)
 
7341
                                enc.Encode (type);
 
7342
 
 
7343
                        if (typearg is InflatedTypeSpec) {
 
7344
                                var gt = typearg;
 
7345
                                do {
 
7346
                                        if (InflatedTypeSpec.ContainsTypeParameter (gt)) {
 
7347
                                                rc.Module.Compiler.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters",
 
7348
                                                        typearg.GetSignatureForError ());
 
7349
                                                return;
 
7350
                                        }
 
7351
 
 
7352
                                        gt = gt.DeclaringType;
 
7353
                                } while (gt != null);
 
7354
                        }
 
7355
 
 
7356
                        if (ContainsDynamicType (typearg)) {
 
7357
                                Attribute.Error_AttributeArgumentIsDynamic (rc, loc);
 
7358
                                return;
 
7359
                        }
 
7360
 
 
7361
                        enc.EncodeTypeName (typearg);
 
7362
                }
 
7363
 
 
7364
                public override void Emit (EmitContext ec)
 
7365
                {
 
7366
                        ec.Emit (OpCodes.Ldtoken, typearg);
 
7367
                        var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc);
 
7368
                        if (m != null)
 
7369
                                ec.Emit (OpCodes.Call, m);
 
7370
                }
 
7371
 
 
7372
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
7373
                {
 
7374
                        TypeOf target = (TypeOf) t;
 
7375
                        if (QueriedType != null)
 
7376
                                target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx);
 
7377
                }
 
7378
 
 
7379
                public override object Accept (StructuralVisitor visitor)
 
7380
                {
 
7381
                        return visitor.Visit (this);
 
7382
                }
 
7383
        }
 
7384
 
 
7385
        sealed class TypeOfMethod : TypeOfMember<MethodSpec>
 
7386
        {
 
7387
                public TypeOfMethod (MethodSpec method, Location loc)
 
7388
                        : base (method, loc)
 
7389
                {
 
7390
                }
 
7391
 
 
7392
                protected override Expression DoResolve (ResolveContext ec)
 
7393
                {
 
7394
                        if (member.IsConstructor) {
 
7395
                                type = ec.Module.PredefinedTypes.ConstructorInfo.Resolve ();
 
7396
                        } else {
 
7397
                                type = ec.Module.PredefinedTypes.MethodInfo.Resolve ();
 
7398
                        }
 
7399
 
 
7400
                        if (type == null)
 
7401
                                return null;
 
7402
 
 
7403
                        return base.DoResolve (ec);
 
7404
                }
 
7405
 
 
7406
                public override void Emit (EmitContext ec)
 
7407
                {
 
7408
                        ec.Emit (OpCodes.Ldtoken, member);
 
7409
 
 
7410
                        base.Emit (ec);
 
7411
                        ec.Emit (OpCodes.Castclass, type);
 
7412
                }
 
7413
 
 
7414
                protected override PredefinedMember<MethodSpec> GetTypeFromHandle (EmitContext ec)
 
7415
                {
 
7416
                        return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle;
 
7417
                }
 
7418
 
 
7419
                protected override PredefinedMember<MethodSpec> GetTypeFromHandleGeneric (EmitContext ec)
 
7420
                {
 
7421
                        return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle2;
 
7422
                }
 
7423
        }
 
7424
 
 
7425
        abstract class TypeOfMember<T> : Expression where T : MemberSpec
 
7426
        {
 
7427
                protected readonly T member;
 
7428
 
 
7429
                protected TypeOfMember (T member, Location loc)
 
7430
                {
 
7431
                        this.member = member;
 
7432
                        this.loc = loc;
 
7433
                }
 
7434
 
 
7435
                public override Expression CreateExpressionTree (ResolveContext ec)
 
7436
                {
 
7437
                        Arguments args = new Arguments (2);
 
7438
                        args.Add (new Argument (this));
 
7439
                        args.Add (new Argument (new TypeOf (type, loc)));
 
7440
                        return CreateExpressionFactoryCall (ec, "Constant", args);
 
7441
                }
 
7442
 
 
7443
                protected override Expression DoResolve (ResolveContext ec)
 
7444
                {
 
7445
                        eclass = ExprClass.Value;
 
7446
                        return this;
 
7447
                }
 
7448
 
 
7449
                public override void Emit (EmitContext ec)
 
7450
                {
 
7451
                        bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric;
 
7452
                        PredefinedMember<MethodSpec> p;
 
7453
                        if (is_generic) {
 
7454
                                p = GetTypeFromHandleGeneric (ec);
 
7455
                                ec.Emit (OpCodes.Ldtoken, member.DeclaringType);
 
7456
                        } else {
 
7457
                                p = GetTypeFromHandle (ec);
 
7458
                        }
 
7459
 
 
7460
                        var mi = p.Resolve (loc);
 
7461
                        if (mi != null)
 
7462
                                ec.Emit (OpCodes.Call, mi);
 
7463
                }
 
7464
 
 
7465
                protected abstract PredefinedMember<MethodSpec> GetTypeFromHandle (EmitContext ec);
 
7466
                protected abstract PredefinedMember<MethodSpec> GetTypeFromHandleGeneric (EmitContext ec);
 
7467
        }
 
7468
 
 
7469
        sealed class TypeOfField : TypeOfMember<FieldSpec>
 
7470
        {
 
7471
                public TypeOfField (FieldSpec field, Location loc)
 
7472
                        : base (field, loc)
 
7473
                {
 
7474
                }
 
7475
 
 
7476
                protected override Expression DoResolve (ResolveContext ec)
 
7477
                {
 
7478
                        type = ec.Module.PredefinedTypes.FieldInfo.Resolve ();
 
7479
                        if (type == null)
 
7480
                                return null;
 
7481
 
 
7482
                        return base.DoResolve (ec);
 
7483
                }
 
7484
 
 
7485
                public override void Emit (EmitContext ec)
 
7486
                {
 
7487
                        ec.Emit (OpCodes.Ldtoken, member);
 
7488
                        base.Emit (ec);
 
7489
                }
 
7490
 
 
7491
                protected override PredefinedMember<MethodSpec> GetTypeFromHandle (EmitContext ec)
 
7492
                {
 
7493
                        return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle;
 
7494
                }
 
7495
 
 
7496
                protected override PredefinedMember<MethodSpec> GetTypeFromHandleGeneric (EmitContext ec)
 
7497
                {
 
7498
                        return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle2;
 
7499
                }
 
7500
        }
 
7501
 
 
7502
        /// <summary>
 
7503
        ///   Implements the sizeof expression
 
7504
        /// </summary>
 
7505
        public class SizeOf : Expression {
 
7506
                public readonly Expression QueriedType;
 
7507
                TypeSpec type_queried;
 
7508
                
 
7509
                public SizeOf (Expression queried_type, Location l)
 
7510
                {
 
7511
                        this.QueriedType = queried_type;
 
7512
                        loc = l;
 
7513
                }
 
7514
 
 
7515
                public override Expression CreateExpressionTree (ResolveContext ec)
 
7516
                {
 
7517
                        Error_PointerInsideExpressionTree (ec);
 
7518
                        return null;
 
7519
                }
 
7520
 
 
7521
                protected override Expression DoResolve (ResolveContext ec)
 
7522
                {
 
7523
                        type_queried = QueriedType.ResolveAsType (ec);
 
7524
                        if (type_queried == null)
 
7525
                                return null;
 
7526
 
 
7527
                        if (TypeManager.IsEnumType (type_queried))
 
7528
                                type_queried = EnumSpec.GetUnderlyingType (type_queried);
 
7529
 
 
7530
                        int size_of = BuiltinTypeSpec.GetSize (type_queried);
 
7531
                        if (size_of > 0) {
 
7532
                                return new IntConstant (ec.BuiltinTypes, size_of, loc);
 
7533
                        }
 
7534
 
 
7535
                        if (!TypeManager.VerifyUnmanaged (ec.Module, type_queried, loc)){
 
7536
                                return null;
 
7537
                        }
 
7538
 
 
7539
                        if (!ec.IsUnsafe) {
 
7540
                                ec.Report.Error (233, loc,
 
7541
                                        "`{0}' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)",
 
7542
                                        TypeManager.CSharpName (type_queried));
 
7543
                        }
 
7544
                        
 
7545
                        type = ec.BuiltinTypes.Int;
 
7546
                        eclass = ExprClass.Value;
 
7547
                        return this;
 
7548
                }
 
7549
 
 
7550
                public override void Emit (EmitContext ec)
 
7551
                {
 
7552
                        ec.Emit (OpCodes.Sizeof, type_queried);
 
7553
                }
 
7554
 
 
7555
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
7556
                {
 
7557
                }
 
7558
                
 
7559
                public override object Accept (StructuralVisitor visitor)
 
7560
                {
 
7561
                        return visitor.Visit (this);
 
7562
                }
 
7563
        }
 
7564
 
 
7565
        /// <summary>
 
7566
        ///   Implements the qualified-alias-member (::) expression.
 
7567
        /// </summary>
 
7568
        public class QualifiedAliasMember : MemberAccess
 
7569
        {
 
7570
                public readonly string alias;
 
7571
                public static readonly string GlobalAlias = "global";
 
7572
 
 
7573
                public QualifiedAliasMember (string alias, string identifier, Location l)
 
7574
                        : base (null, identifier, l)
 
7575
                {
 
7576
                        this.alias = alias;
 
7577
                }
 
7578
 
 
7579
                public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l)
 
7580
                        : base (null, identifier, targs, l)
 
7581
                {
 
7582
                        this.alias = alias;
 
7583
                }
 
7584
 
 
7585
                public QualifiedAliasMember (string alias, string identifier, int arity, Location l)
 
7586
                        : base (null, identifier, arity, l)
 
7587
                {
 
7588
                        this.alias = alias;
 
7589
                }
 
7590
 
 
7591
                public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec)
 
7592
                {
 
7593
                        if (alias == GlobalAlias) {
 
7594
                                expr = ec.Module.GlobalRootNamespace;
 
7595
                                return base.ResolveAsTypeOrNamespace (ec);
 
7596
                        }
 
7597
 
 
7598
                        int errors = ec.Module.Compiler.Report.Errors;
 
7599
                        expr = ec.LookupNamespaceAlias (alias);
 
7600
                        if (expr == null) {
 
7601
                                if (errors == ec.Module.Compiler.Report.Errors)
 
7602
                                        ec.Module.Compiler.Report.Error (432, loc, "Alias `{0}' not found", alias);
 
7603
                                return null;
 
7604
                        }
 
7605
 
 
7606
                        FullNamedExpression fne = base.ResolveAsTypeOrNamespace (ec);
 
7607
                        if (fne == null)
 
7608
                                return null;
 
7609
 
 
7610
                        if (expr.eclass == ExprClass.Type) {
 
7611
                                ec.Module.Compiler.Report.Error (431, loc,
 
7612
                                        "Alias `{0}' cannot be used with '::' since it denotes a type. Consider replacing '::' with '.'", alias);
 
7613
 
 
7614
                                return null;
 
7615
                        }
 
7616
 
 
7617
                        return fne;
 
7618
                }
 
7619
 
 
7620
                protected override Expression DoResolve (ResolveContext ec)
 
7621
                {
 
7622
                        return ResolveAsTypeOrNamespace (ec);
 
7623
                }
 
7624
 
 
7625
                protected override void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier)
 
7626
                {
 
7627
                        rc.Module.Compiler.Report.Error (687, loc,
 
7628
                                "A namespace alias qualifier `{0}' did not resolve to a namespace or a type",
 
7629
                                GetSignatureForError ());
 
7630
                }
 
7631
 
 
7632
                public override string GetSignatureForError ()
 
7633
                {
 
7634
                        string name = Name;
 
7635
                        if (targs != null) {
 
7636
                                name = Name + "<" + targs.GetSignatureForError () + ">";
 
7637
                        }
 
7638
 
 
7639
                        return alias + "::" + name;
 
7640
                }
 
7641
 
 
7642
                public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
 
7643
                {
 
7644
                        return DoResolve (rc);
 
7645
                }
 
7646
 
 
7647
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
7648
                {
 
7649
                        // Nothing 
 
7650
                }
 
7651
                
 
7652
                public override object Accept (StructuralVisitor visitor)
 
7653
                {
 
7654
                        return visitor.Visit (this);
 
7655
                }
 
7656
        }
 
7657
 
 
7658
        /// <summary>
 
7659
        ///   Implements the member access expression
 
7660
        /// </summary>
 
7661
        public class MemberAccess : ATypeNameExpression
 
7662
        {
 
7663
                protected Expression expr;
 
7664
 
 
7665
                public MemberAccess (Expression expr, string id)
 
7666
                        : base (id, expr.Location)
 
7667
                {
 
7668
                        this.expr = expr;
 
7669
                }
 
7670
 
 
7671
                public MemberAccess (Expression expr, string identifier, Location loc)
 
7672
                        : base (identifier, loc)
 
7673
                {
 
7674
                        this.expr = expr;
 
7675
                }
 
7676
 
 
7677
                public MemberAccess (Expression expr, string identifier, TypeArguments args, Location loc)
 
7678
                        : base (identifier, args, loc)
 
7679
                {
 
7680
                        this.expr = expr;
 
7681
                }
 
7682
 
 
7683
                public MemberAccess (Expression expr, string identifier, int arity, Location loc)
 
7684
                        : base (identifier, arity, loc)
 
7685
                {
 
7686
                        this.expr = expr;
 
7687
                }
 
7688
 
 
7689
                public Expression LeftExpression {
 
7690
                        get {
 
7691
                                return expr;
 
7692
                        }
 
7693
                }
 
7694
 
 
7695
                protected override Expression DoResolve (ResolveContext ec)
 
7696
                {
 
7697
                        return DoResolveName (ec, null);
 
7698
                }
 
7699
 
 
7700
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
7701
                {
 
7702
                        return DoResolveName (ec, right_side);
 
7703
                }
 
7704
 
 
7705
                Expression DoResolveName (ResolveContext rc, Expression right_side)
 
7706
                {
 
7707
                        Expression e = LookupNameExpression (rc, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
 
7708
                        if (e == null)
 
7709
                                return null;
 
7710
 
 
7711
                        if (right_side != null) {
 
7712
                                if (e is TypeExpr) {
 
7713
                                        e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
 
7714
                                        return null;
 
7715
                                }
 
7716
 
 
7717
                                e = e.ResolveLValue (rc, right_side);
 
7718
                        } else {
 
7719
                                e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type);
 
7720
                        }
 
7721
 
 
7722
                        return e;
 
7723
                }
 
7724
 
 
7725
                public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions)
 
7726
                {
 
7727
                        var sn = expr as SimpleName;
 
7728
                        const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
 
7729
 
 
7730
                        //
 
7731
                        // Resolve the expression with flow analysis turned off, we'll do the definite
 
7732
                        // assignment checks later.  This is because we don't know yet what the expression
 
7733
                        // will resolve to - it may resolve to a FieldExpr and in this case we must do the
 
7734
                        // definite assignment check on the actual field and not on the whole struct.
 
7735
                        //
 
7736
                        using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
 
7737
                                if (sn != null) {
 
7738
                                        expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
 
7739
 
 
7740
                                        // Call resolve on expression which does have type set as we need expression type
 
7741
                                        // TODO: I should probably ensure that the type is always set and leave resolve for the final
 
7742
                                        if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
 
7743
                                                using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
 
7744
                                                        expr = expr.Resolve (rc);
 
7745
                                                }
 
7746
                                        } else if (expr is TypeParameterExpr) {
 
7747
                                                expr.Error_UnexpectedKind (rc, flags, sn.Location);
 
7748
                                                expr = null;
 
7749
                                        }
 
7750
                                } else {
 
7751
                                        expr = expr.Resolve (rc, flags);
 
7752
                                }
 
7753
                        }
 
7754
 
 
7755
                        if (expr == null)
 
7756
                                return null;
 
7757
 
 
7758
                        Namespace ns = expr as Namespace;
 
7759
                        if (ns != null) {
 
7760
                                var retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc);
 
7761
 
 
7762
                                if (retval == null) {
 
7763
                                        ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc);
 
7764
                                        return null;
 
7765
                                }
 
7766
 
 
7767
                                if (HasTypeArguments)
 
7768
                                        return new GenericTypeExpr (retval.Type, targs, loc);
 
7769
 
 
7770
                                return retval;
 
7771
                        }
 
7772
 
 
7773
                        MemberExpr me;
 
7774
                        TypeSpec expr_type = expr.Type;
 
7775
                        if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
7776
                                me = expr as MemberExpr;
 
7777
                                if (me != null)
 
7778
                                        me.ResolveInstanceExpression (rc, null);
 
7779
 
 
7780
                                Arguments args = new Arguments (1);
 
7781
                                args.Add (new Argument (expr));
 
7782
                                return new DynamicMemberBinder (Name, args, loc);
 
7783
                        }
 
7784
 
 
7785
                        const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum |
 
7786
                                MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType;
 
7787
 
 
7788
                        if ((expr_type.Kind & dot_kinds) == 0) {
 
7789
                                if (expr_type == InternalType.NullLiteral && rc.IsRuntimeBinder)
 
7790
                                        rc.Report.Error (Report.RuntimeErrorId, loc, "Cannot perform member binding on `null' value");
 
7791
                                else
 
7792
                                        Unary.Error_OperatorCannotBeApplied (rc, loc, ".", expr_type);
 
7793
                                return null;
 
7794
                        }
 
7795
 
 
7796
                        var lookup_arity = Arity;
 
7797
                        bool errorMode = false;
 
7798
                        Expression member_lookup;
 
7799
                        while (true) {
 
7800
                                member_lookup = MemberLookup (rc, errorMode, expr_type, Name, lookup_arity, restrictions, loc);
 
7801
                                if (member_lookup == null) {
 
7802
                                        //
 
7803
                                        // Try to look for extension method when member lookup failed
 
7804
                                        //
 
7805
                                        if (MethodGroupExpr.IsExtensionMethodArgument (expr)) {
 
7806
                                                NamespaceContainer scope = null;
 
7807
                                                var methods = rc.LookupExtensionMethod (expr_type, Name, lookup_arity, ref scope);
 
7808
                                                if (methods != null) {
 
7809
                                                        var emg = new ExtensionMethodGroupExpr (methods, scope, expr, loc);
 
7810
                                                        if (HasTypeArguments) {
 
7811
                                                                if (!targs.Resolve (rc))
 
7812
                                                                        return null;
 
7813
 
 
7814
                                                                emg.SetTypeArguments (rc, targs);
 
7815
                                                        }
 
7816
 
 
7817
                                                        // TODO: it should really skip the checks bellow
 
7818
                                                        return emg.Resolve (rc);
 
7819
                                                }
 
7820
                                        }
 
7821
                                }
 
7822
 
 
7823
                                if (errorMode) {
 
7824
                                        if (member_lookup == null) {
 
7825
                                                var dep = expr_type.GetMissingDependencies ();
 
7826
                                                if (dep != null) {
 
7827
                                                        ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc);
 
7828
                                                } else if (expr is TypeExpr) {
 
7829
                                                        base.Error_TypeDoesNotContainDefinition (rc, expr_type, Name);
 
7830
                                                } else {
 
7831
                                                        Error_TypeDoesNotContainDefinition (rc, expr_type, Name);
 
7832
                                                }
 
7833
 
 
7834
                                                return null;
 
7835
                                        }
 
7836
 
 
7837
                                        if (member_lookup is MethodGroupExpr) {
 
7838
                                                // Leave it to overload resolution to report correct error
 
7839
                                        } else if (!(member_lookup is TypeExpr)) {
 
7840
                                                // TODO: rc.SymbolRelatedToPreviousError
 
7841
                                                ErrorIsInaccesible (rc, member_lookup.GetSignatureForError (), loc);
 
7842
                                        }
 
7843
                                        break;
 
7844
                                }
 
7845
 
 
7846
                                if (member_lookup != null)
 
7847
                                        break;
 
7848
 
 
7849
                                lookup_arity = 0;
 
7850
                                restrictions &= ~MemberLookupRestrictions.InvocableOnly;
 
7851
                                errorMode = true;
 
7852
                        }
 
7853
 
 
7854
                        TypeExpr texpr = member_lookup as TypeExpr;
 
7855
                        if (texpr != null) {
 
7856
                                if (!(expr is TypeExpr)) {
 
7857
                                        me = expr as MemberExpr;
 
7858
                                        if (me == null || me.ProbeIdenticalTypeName (rc, expr, sn) == expr) {
 
7859
                                                rc.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead",
 
7860
                                                        Name, member_lookup.GetSignatureForError ());
 
7861
                                                return null;
 
7862
                                        }
 
7863
                                }
 
7864
 
 
7865
                                if (!texpr.Type.IsAccessible (rc)) {
 
7866
                                        rc.Report.SymbolRelatedToPreviousError (member_lookup.Type);
 
7867
                                        ErrorIsInaccesible (rc, member_lookup.Type.GetSignatureForError (), loc);
 
7868
                                        return null;
 
7869
                                }
 
7870
 
 
7871
                                if (HasTypeArguments) {
 
7872
                                        return new GenericTypeExpr (member_lookup.Type, targs, loc);
 
7873
                                }
 
7874
 
 
7875
                                return member_lookup;
 
7876
                        }
 
7877
 
 
7878
                        me = member_lookup as MemberExpr;
 
7879
 
 
7880
                        if (sn != null && me.IsStatic)
 
7881
                                expr = me.ProbeIdenticalTypeName (rc, expr, sn);
 
7882
 
 
7883
                        me = me.ResolveMemberAccess (rc, expr, sn);
 
7884
 
 
7885
                        if (Arity > 0) {
 
7886
                                if (!targs.Resolve (rc))
 
7887
                                        return null;
 
7888
 
 
7889
                                me.SetTypeArguments (rc, targs);
 
7890
                        }
 
7891
 
 
7892
                        if (sn != null && (!TypeSpec.IsValueType (expr_type) || me is PropertyExpr)) {
 
7893
                                if (me.IsInstance) {
 
7894
                                        LocalVariableReference var = expr as LocalVariableReference;
 
7895
                                        if (var != null && !var.VerifyAssigned (rc))
 
7896
                                                return null;
 
7897
                                }
 
7898
                        }
 
7899
 
 
7900
                        return me;
 
7901
                }
 
7902
 
 
7903
                public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext rc)
 
7904
                {
 
7905
                        FullNamedExpression fexpr = expr as FullNamedExpression;
 
7906
                        if (fexpr == null) {
 
7907
                                expr.ResolveAsType (rc);
 
7908
                                return null;
 
7909
                        }
 
7910
 
 
7911
                        FullNamedExpression expr_resolved = fexpr.ResolveAsTypeOrNamespace (rc);
 
7912
 
 
7913
                        if (expr_resolved == null)
 
7914
                                return null;
 
7915
 
 
7916
                        Namespace ns = expr_resolved as Namespace;
 
7917
                        if (ns != null) {
 
7918
                                FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc);
 
7919
 
 
7920
                                if (retval == null) {
 
7921
                                        ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc);
 
7922
                                } else if (HasTypeArguments) {
 
7923
                                        retval = new GenericTypeExpr (retval.Type, targs, loc);
 
7924
                                        if (retval.ResolveAsType (rc) == null)
 
7925
                                                return null;
 
7926
                                }
 
7927
 
 
7928
                                return retval;
 
7929
                        }
 
7930
 
 
7931
                        var tnew_expr = expr_resolved.ResolveAsType (rc);
 
7932
                        if (tnew_expr == null)
 
7933
                                return null;
 
7934
 
 
7935
                        TypeSpec expr_type = tnew_expr;
 
7936
                        if (TypeManager.IsGenericParameter (expr_type)) {
 
7937
                                rc.Module.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'",
 
7938
                                        tnew_expr.GetSignatureForError ());
 
7939
                                return null;
 
7940
                        }
 
7941
 
 
7942
                        TypeSpec nested = null;
 
7943
                        while (expr_type != null) {
 
7944
                                nested = MemberCache.FindNestedType (expr_type, Name, Arity);
 
7945
                                if (nested == null) {
 
7946
                                        if (expr_type == tnew_expr) {
 
7947
                                                Error_IdentifierNotFound (rc, expr_type, Name);
 
7948
                                                return null;
 
7949
                                        }
 
7950
 
 
7951
                                        expr_type = tnew_expr;
 
7952
                                        nested = MemberCache.FindNestedType (expr_type, Name, Arity);
 
7953
                                        ErrorIsInaccesible (rc, nested.GetSignatureForError (), loc);
 
7954
                                        break;
 
7955
                                }
 
7956
 
 
7957
                                if (nested.IsAccessible (rc))
 
7958
                                        break;
 
7959
 
 
7960
                                // Keep looking after inaccessible candidate
 
7961
                                expr_type = nested.DeclaringType.BaseType;
 
7962
                        }
 
7963
                        
 
7964
                        TypeExpr texpr;
 
7965
                        if (Arity > 0) {
 
7966
                                if (HasTypeArguments) {
 
7967
                                        texpr = new GenericTypeExpr (nested, targs, loc);
 
7968
                                } else {
 
7969
                                        texpr = new GenericOpenTypeExpr (nested, loc);
 
7970
                                }
 
7971
                        } else {
 
7972
                                texpr = new TypeExpression (nested, loc);
 
7973
                        }
 
7974
 
 
7975
                        if (texpr.ResolveAsType (rc) == null)
 
7976
                                return null;
 
7977
 
 
7978
                        return texpr;
 
7979
                }
 
7980
 
 
7981
                protected virtual void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier)
 
7982
                {
 
7983
                        var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity));
 
7984
 
 
7985
                        if (nested != null) {
 
7986
                                Error_TypeArgumentsCannotBeUsed (rc, nested, Arity, expr.Location);
 
7987
                                return;
 
7988
                        }
 
7989
 
 
7990
                        var any_other_member = MemberLookup (rc, true, expr_type, Name, 0, MemberLookupRestrictions.None, loc);
 
7991
                        if (any_other_member != null) {
 
7992
                                any_other_member.Error_UnexpectedKind (rc.Module.Compiler.Report, null, "type", loc);
 
7993
                                return;
 
7994
                        }
 
7995
 
 
7996
                        rc.Module.Compiler.Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
 
7997
                                Name, expr_type.GetSignatureForError ());
 
7998
                }
 
7999
 
 
8000
                protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
 
8001
                {
 
8002
                        if (ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2 && !ec.IsRuntimeBinder && MethodGroupExpr.IsExtensionMethodArgument (expr)) {
 
8003
                                ec.Report.SymbolRelatedToPreviousError (type);
 
8004
                                ec.Report.Error (1061, loc,
 
8005
                                        "Type `{0}' does not contain a definition for `{1}' and no extension method `{1}' of type `{0}' could be found (are you missing a using directive or an assembly reference?)",
 
8006
                                        type.GetSignatureForError (), name);
 
8007
                                return;
 
8008
                        }
 
8009
 
 
8010
                        base.Error_TypeDoesNotContainDefinition (ec, type, name);
 
8011
                }
 
8012
 
 
8013
                public override string GetSignatureForError ()
 
8014
                {
 
8015
                        return expr.GetSignatureForError () + "." + base.GetSignatureForError ();
 
8016
                }
 
8017
 
 
8018
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
8019
                {
 
8020
                        MemberAccess target = (MemberAccess) t;
 
8021
 
 
8022
                        target.expr = expr.Clone (clonectx);
 
8023
                }
 
8024
                
 
8025
                public override object Accept (StructuralVisitor visitor)
 
8026
                {
 
8027
                        return visitor.Visit (this);
 
8028
                }
 
8029
        }
 
8030
 
 
8031
        /// <summary>
 
8032
        ///   Implements checked expressions
 
8033
        /// </summary>
 
8034
        public class CheckedExpr : Expression {
 
8035
 
 
8036
                public Expression Expr;
 
8037
                
 
8038
                public CheckedExpr (Expression e, Location l)
 
8039
                {
 
8040
                        Expr = e;
 
8041
                        loc = l;
 
8042
                }
 
8043
                
 
8044
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8045
                {
 
8046
                        using (ec.With (ResolveContext.Options.AllCheckStateFlags, true))
 
8047
                                return Expr.CreateExpressionTree (ec);
 
8048
                }
 
8049
 
 
8050
                protected override Expression DoResolve (ResolveContext ec)
 
8051
                {
 
8052
                        using (ec.With (ResolveContext.Options.AllCheckStateFlags, true))
 
8053
                                Expr = Expr.Resolve (ec);
 
8054
                        
 
8055
                        if (Expr == null)
 
8056
                                return null;
 
8057
 
 
8058
                        if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression)
 
8059
                                return Expr;
 
8060
                        
 
8061
                        eclass = Expr.eclass;
 
8062
                        type = Expr.Type;
 
8063
                        return this;
 
8064
                }
 
8065
 
 
8066
                public override void Emit (EmitContext ec)
 
8067
                {
 
8068
                        using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
 
8069
                                Expr.Emit (ec);
 
8070
                }
 
8071
 
 
8072
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 
8073
                {
 
8074
                        using (ec.With (EmitContext.Options.AllCheckStateFlags, true))
 
8075
                                Expr.EmitBranchable (ec, target, on_true);
 
8076
                }
 
8077
 
 
8078
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
8079
                {
 
8080
                        using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) {
 
8081
                                return Expr.MakeExpression (ctx);
 
8082
                        }
 
8083
                }
 
8084
 
 
8085
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
8086
                {
 
8087
                        CheckedExpr target = (CheckedExpr) t;
 
8088
 
 
8089
                        target.Expr = Expr.Clone (clonectx);
 
8090
                }
 
8091
                public override object Accept (StructuralVisitor visitor)
 
8092
                {
 
8093
                        return visitor.Visit (this);
 
8094
                }
 
8095
        }
 
8096
 
 
8097
        /// <summary>
 
8098
        ///   Implements the unchecked expression
 
8099
        /// </summary>
 
8100
        public class UnCheckedExpr : Expression {
 
8101
 
 
8102
                public Expression Expr;
 
8103
 
 
8104
                public UnCheckedExpr (Expression e, Location l)
 
8105
                {
 
8106
                        Expr = e;
 
8107
                        loc = l;
 
8108
                }
 
8109
                
 
8110
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8111
                {
 
8112
                        using (ec.With (ResolveContext.Options.AllCheckStateFlags, false))
 
8113
                                return Expr.CreateExpressionTree (ec);
 
8114
                }
 
8115
 
 
8116
                protected override Expression DoResolve (ResolveContext ec)
 
8117
                {
 
8118
                        using (ec.With (ResolveContext.Options.AllCheckStateFlags, false))
 
8119
                                Expr = Expr.Resolve (ec);
 
8120
 
 
8121
                        if (Expr == null)
 
8122
                                return null;
 
8123
 
 
8124
                        if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression)
 
8125
                                return Expr;
 
8126
                        
 
8127
                        eclass = Expr.eclass;
 
8128
                        type = Expr.Type;
 
8129
                        return this;
 
8130
                }
 
8131
 
 
8132
                public override void Emit (EmitContext ec)
 
8133
                {
 
8134
                        using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
 
8135
                                Expr.Emit (ec);
 
8136
                }
 
8137
 
 
8138
                public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
 
8139
                {
 
8140
                        using (ec.With (EmitContext.Options.AllCheckStateFlags, false))
 
8141
                                Expr.EmitBranchable (ec, target, on_true);
 
8142
                }
 
8143
 
 
8144
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
8145
                {
 
8146
                        UnCheckedExpr target = (UnCheckedExpr) t;
 
8147
 
 
8148
                        target.Expr = Expr.Clone (clonectx);
 
8149
                }
 
8150
                public override object Accept (StructuralVisitor visitor)
 
8151
                {
 
8152
                        return visitor.Visit (this);
 
8153
                }
 
8154
        }
 
8155
 
 
8156
        /// <summary>
 
8157
        ///   An Element Access expression.
 
8158
        ///
 
8159
        ///   During semantic analysis these are transformed into 
 
8160
        ///   IndexerAccess, ArrayAccess or a PointerArithmetic.
 
8161
        /// </summary>
 
8162
        public class ElementAccess : Expression {
 
8163
                public Arguments Arguments;
 
8164
                public Expression Expr;
 
8165
 
 
8166
                public ElementAccess (Expression e, Arguments args, Location loc)
 
8167
                {
 
8168
                        Expr = e;
 
8169
                        this.loc = loc;
 
8170
                        this.Arguments = args;
 
8171
                }
 
8172
 
 
8173
                //
 
8174
                // We perform some simple tests, and then to "split" the emit and store
 
8175
                // code we create an instance of a different class, and return that.
 
8176
                //
 
8177
                Expression CreateAccessExpression (ResolveContext ec)
 
8178
                {
 
8179
                        if (type.IsArray)
 
8180
                                return (new ArrayAccess (this, loc));
 
8181
 
 
8182
                        if (type.IsPointer)
 
8183
                                return MakePointerAccess (ec, type);
 
8184
 
 
8185
                        FieldExpr fe = Expr as FieldExpr;
 
8186
                        if (fe != null) {
 
8187
                                var ff = fe.Spec as FixedFieldSpec;
 
8188
                                if (ff != null) {
 
8189
                                        return MakePointerAccess (ec, ff.ElementType);
 
8190
                                }
 
8191
                        }
 
8192
 
 
8193
                        var indexers = MemberCache.FindMembers (type, MemberCache.IndexerNameAlias, false);
 
8194
                        if (indexers != null || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
8195
                                return new IndexerExpr (indexers, type, this);
 
8196
                        }
 
8197
 
 
8198
                        ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'",
 
8199
                                type.GetSignatureForError ());
 
8200
                        return null;
 
8201
                }
 
8202
 
 
8203
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8204
                {
 
8205
                        Arguments args = Arguments.CreateForExpressionTree (ec, Arguments,
 
8206
                                Expr.CreateExpressionTree (ec));
 
8207
 
 
8208
                        return CreateExpressionFactoryCall (ec, "ArrayIndex", args);
 
8209
                }
 
8210
 
 
8211
                Expression MakePointerAccess (ResolveContext ec, TypeSpec type)
 
8212
                {
 
8213
                        if (Arguments.Count != 1){
 
8214
                                ec.Report.Error (196, loc, "A pointer must be indexed by only one value");
 
8215
                                return null;
 
8216
                        }
 
8217
 
 
8218
                        if (Arguments [0] is NamedArgument)
 
8219
                                Error_NamedArgument ((NamedArgument) Arguments[0], ec.Report);
 
8220
 
 
8221
                        Expression p = new PointerArithmetic (Binary.Operator.Addition, Expr, Arguments [0].Expr.Resolve (ec), type, loc);
 
8222
                        return new Indirection (p, loc);
 
8223
                }
 
8224
                
 
8225
                protected override Expression DoResolve (ResolveContext ec)
 
8226
                {
 
8227
                        Expr = Expr.Resolve (ec);
 
8228
                        if (Expr == null)
 
8229
                                return null;
 
8230
 
 
8231
                        type = Expr.Type;
 
8232
 
 
8233
                        // TODO: Create 1 result for Resolve and ResolveLValue ?
 
8234
                        var res = CreateAccessExpression (ec);
 
8235
                        if (res == null)
 
8236
                                return null;
 
8237
 
 
8238
                        return res.Resolve (ec);
 
8239
                }
 
8240
 
 
8241
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
8242
                {
 
8243
                        Expr = Expr.Resolve (ec);
 
8244
                        if (Expr == null)
 
8245
                                return null;
 
8246
 
 
8247
                        type = Expr.Type;
 
8248
 
 
8249
                        var res = CreateAccessExpression (ec);
 
8250
                        if (res == null)
 
8251
                                return null;
 
8252
 
 
8253
                        return res.ResolveLValue (ec, right_side);
 
8254
                }
 
8255
                
 
8256
                public override void Emit (EmitContext ec)
 
8257
                {
 
8258
                        throw new Exception ("Should never be reached");
 
8259
                }
 
8260
 
 
8261
                public static void Error_NamedArgument (NamedArgument na, Report Report)
 
8262
                {
 
8263
                        Report.Error (1742, na.Location, "An element access expression cannot use named argument");
 
8264
                }
 
8265
 
 
8266
                public override string GetSignatureForError ()
 
8267
                {
 
8268
                        return Expr.GetSignatureForError ();
 
8269
                }
 
8270
 
 
8271
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
8272
                {
 
8273
                        ElementAccess target = (ElementAccess) t;
 
8274
 
 
8275
                        target.Expr = Expr.Clone (clonectx);
 
8276
                        if (Arguments != null)
 
8277
                                target.Arguments = Arguments.Clone (clonectx);
 
8278
                }
 
8279
                
 
8280
                public override object Accept (StructuralVisitor visitor)
 
8281
                {
 
8282
                        return visitor.Visit (this);
 
8283
                }
 
8284
        }
 
8285
 
 
8286
        /// <summary>
 
8287
        ///   Implements array access 
 
8288
        /// </summary>
 
8289
        public class ArrayAccess : Expression, IDynamicAssign, IMemoryLocation {
 
8290
                //
 
8291
                // Points to our "data" repository
 
8292
                //
 
8293
                ElementAccess ea;
 
8294
 
 
8295
                LocalTemporary temp, expr_copy;
 
8296
                Expression[] prepared_arguments;
 
8297
                bool prepared;
 
8298
                
 
8299
                public ArrayAccess (ElementAccess ea_data, Location l)
 
8300
                {
 
8301
                        ea = ea_data;
 
8302
                        loc = l;
 
8303
                }
 
8304
 
 
8305
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8306
                {
 
8307
                        return ea.CreateExpressionTree (ec);
 
8308
                }
 
8309
 
 
8310
                public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
8311
                {
 
8312
                        return DoResolve (ec);
 
8313
                }
 
8314
 
 
8315
                protected override Expression DoResolve (ResolveContext ec)
 
8316
                {
 
8317
                        // dynamic is used per argument in ConvertExpressionToArrayIndex case
 
8318
                        bool dynamic;
 
8319
                        ea.Arguments.Resolve (ec, out dynamic);
 
8320
 
 
8321
                        var ac = ea.Expr.Type as ArrayContainer;
 
8322
                        int rank = ea.Arguments.Count;
 
8323
                        if (ac.Rank != rank) {
 
8324
                                ec.Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'",
 
8325
                                          rank.ToString (), ac.Rank.ToString ());
 
8326
                                return null;
 
8327
                        }
 
8328
 
 
8329
                        type = ac.Element;
 
8330
                        if (type.IsPointer && !ec.IsUnsafe) {
 
8331
                                UnsafeError (ec, ea.Location);
 
8332
                        }
 
8333
 
 
8334
                        foreach (Argument a in ea.Arguments) {
 
8335
                                if (a is NamedArgument)
 
8336
                                        ElementAccess.Error_NamedArgument ((NamedArgument) a, ec.Report);
 
8337
 
 
8338
                                a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr);
 
8339
                        }
 
8340
                        
 
8341
                        eclass = ExprClass.Variable;
 
8342
 
 
8343
                        return this;
 
8344
                }
 
8345
 
 
8346
                protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
 
8347
                {
 
8348
                        ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
 
8349
                }
 
8350
 
 
8351
                //
 
8352
                // Load the array arguments into the stack.
 
8353
                //
 
8354
                void LoadArrayAndArguments (EmitContext ec)
 
8355
                {
 
8356
                        ea.Expr.Emit (ec);
 
8357
                        ea.Arguments.Emit (ec);
 
8358
                }
 
8359
 
 
8360
                public void Emit (EmitContext ec, bool leave_copy)
 
8361
                {
 
8362
                        var ac = ea.Expr.Type as ArrayContainer;
 
8363
 
 
8364
                        if (prepared) {
 
8365
                                ec.EmitLoadFromPtr (type);
 
8366
                        } else {
 
8367
                                if (prepared_arguments == null) {
 
8368
                                        LoadArrayAndArguments (ec);
 
8369
                                } else {
 
8370
                                        expr_copy.Emit (ec);
 
8371
                                        LocalTemporary lt;
 
8372
                                        foreach (var expr in prepared_arguments) {
 
8373
                                                expr.Emit (ec);
 
8374
                                                lt = expr as LocalTemporary;
 
8375
                                                if (lt != null)
 
8376
                                                        lt.Release (ec);
 
8377
                                        }
 
8378
                                }
 
8379
 
 
8380
                                ec.EmitArrayLoad (ac);
 
8381
                        }       
 
8382
 
 
8383
                        if (leave_copy) {
 
8384
                                ec.Emit (OpCodes.Dup);
 
8385
                                temp = new LocalTemporary (this.type);
 
8386
                                temp.Store (ec);
 
8387
                        }
 
8388
                }
 
8389
                
 
8390
                public override void Emit (EmitContext ec)
 
8391
                {
 
8392
                        Emit (ec, false);
 
8393
                }
 
8394
 
 
8395
                public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
 
8396
                {
 
8397
                        var ac = (ArrayContainer) ea.Expr.Type;
 
8398
                        TypeSpec t = source.Type;
 
8399
 
 
8400
                        //
 
8401
                        // When we are dealing with a struct, get the address of it to avoid value copy
 
8402
                        // Same cannot be done for reference type because array covariance and the
 
8403
                        // check in ldelema requires to specify the type of array element stored at the index
 
8404
                        //
 
8405
                        if (t.IsStruct && ((prepare_for_load && !(source is DynamicExpressionStatement)) || !BuiltinTypeSpec.IsPrimitiveType (t))) {
 
8406
                                LoadArrayAndArguments (ec);
 
8407
                                ec.EmitArrayAddress (ac);
 
8408
 
 
8409
                                if (prepare_for_load) {
 
8410
                                        ec.Emit (OpCodes.Dup);
 
8411
                                }
 
8412
 
 
8413
                                prepared = true;
 
8414
                        } else if (prepare_for_load) {
 
8415
                                ea.Expr.Emit (ec);
 
8416
                                ec.Emit (OpCodes.Dup);
 
8417
 
 
8418
                                expr_copy = new LocalTemporary (ea.Expr.Type);
 
8419
                                expr_copy.Store (ec);
 
8420
                                prepared_arguments = ea.Arguments.Emit (ec, true);
 
8421
                        } else {
 
8422
                                LoadArrayAndArguments (ec);
 
8423
                        }
 
8424
 
 
8425
                        source.Emit (ec);
 
8426
 
 
8427
                        if (expr_copy != null) {
 
8428
                                expr_copy.Release (ec);
 
8429
                        }
 
8430
 
 
8431
                        if (leave_copy) {
 
8432
                                ec.Emit (OpCodes.Dup);
 
8433
                                temp = new LocalTemporary (this.type);
 
8434
                                temp.Store (ec);
 
8435
                        }
 
8436
 
 
8437
                        if (prepared) {
 
8438
                                ec.EmitStoreFromPtr (t);
 
8439
                        } else {
 
8440
                                ec.EmitArrayStore (ac);
 
8441
                        }
 
8442
                        
 
8443
                        if (temp != null) {
 
8444
                                temp.Emit (ec);
 
8445
                                temp.Release (ec);
 
8446
                        }
 
8447
                }
 
8448
 
 
8449
                public void EmitNew (EmitContext ec, New source, bool leave_copy)
 
8450
                {
 
8451
                        if (!source.Emit (ec, this)) {
 
8452
                                if (leave_copy)
 
8453
                                        throw new NotImplementedException ();
 
8454
 
 
8455
                                return;
 
8456
                        }
 
8457
 
 
8458
                        throw new NotImplementedException ();
 
8459
                }
 
8460
 
 
8461
                public void AddressOf (EmitContext ec, AddressOp mode)
 
8462
                {
 
8463
                        var ac = (ArrayContainer) ea.Expr.Type;
 
8464
 
 
8465
                        LoadArrayAndArguments (ec);
 
8466
 
 
8467
                        if (ac.Element.IsGenericParameter && mode == AddressOp.Load)
 
8468
                                ec.Emit (OpCodes.Readonly);
 
8469
 
 
8470
                        ec.EmitArrayAddress (ac);
 
8471
                }
 
8472
 
 
8473
                public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
 
8474
                {
 
8475
#if NET_4_0
 
8476
                        return SLE.Expression.ArrayAccess (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx));
 
8477
#else
 
8478
                        throw new NotImplementedException ();
 
8479
#endif
 
8480
                }
 
8481
 
 
8482
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
8483
                {
 
8484
                        return SLE.Expression.ArrayIndex (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx));
 
8485
                }
 
8486
 
 
8487
                SLE.Expression[] MakeExpressionArguments (BuilderContext ctx)
 
8488
                {
 
8489
                        using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) {
 
8490
                                return Arguments.MakeExpression (ea.Arguments, ctx);
 
8491
                        }
 
8492
                }
 
8493
        }
 
8494
 
 
8495
        //
 
8496
        // Indexer access expression
 
8497
        //
 
8498
        class IndexerExpr : PropertyOrIndexerExpr<IndexerSpec>, OverloadResolver.IBaseMembersProvider
 
8499
        {
 
8500
                LocalTemporary prepared_value;
 
8501
                IList<MemberSpec> indexers;
 
8502
                Arguments arguments;
 
8503
                TypeSpec queried_type;
 
8504
                
 
8505
                public IndexerExpr (IList<MemberSpec> indexers, TypeSpec queriedType, ElementAccess ea)
 
8506
                        : base (ea.Location)
 
8507
                {
 
8508
                        this.indexers = indexers;
 
8509
                        this.queried_type = queriedType;
 
8510
                        this.InstanceExpression = ea.Expr;
 
8511
                        this.arguments = ea.Arguments;
 
8512
                }
 
8513
 
 
8514
                #region Properties
 
8515
                protected override TypeSpec DeclaringType {
 
8516
                        get {
 
8517
                                return best_candidate.DeclaringType;
 
8518
                        }
 
8519
                }
 
8520
 
 
8521
                public override bool IsInstance {
 
8522
                        get {
 
8523
                                return true;
 
8524
                        }
 
8525
                }
 
8526
 
 
8527
                public override bool IsStatic {
 
8528
                        get {
 
8529
                                return false;
 
8530
                        }
 
8531
                }
 
8532
 
 
8533
                public override string Name {
 
8534
                        get {
 
8535
                                return "this";
 
8536
                        }
 
8537
                }
 
8538
 
 
8539
                #endregion
 
8540
 
 
8541
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8542
                {
 
8543
                        Arguments args = Arguments.CreateForExpressionTree (ec, arguments,
 
8544
                                InstanceExpression.CreateExpressionTree (ec),
 
8545
                                new TypeOfMethod (Getter, loc));
 
8546
 
 
8547
                        return CreateExpressionFactoryCall (ec, "Call", args);
 
8548
                }
 
8549
 
 
8550
                public override void Emit (EmitContext ec, bool leave_copy)
 
8551
                {
 
8552
                        if (prepared) {
 
8553
                                prepared_value.Emit (ec);
 
8554
                        } else {
 
8555
                                Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc);
 
8556
                        }
 
8557
 
 
8558
                        if (leave_copy) {
 
8559
                                ec.Emit (OpCodes.Dup);
 
8560
                                temp = new LocalTemporary (Type);
 
8561
                                temp.Store (ec);
 
8562
                        }
 
8563
                }
 
8564
                
 
8565
                public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
 
8566
                {
 
8567
                        prepared = prepare_for_load;
 
8568
                        Expression value = source;
 
8569
 
 
8570
                        if (prepared) {
 
8571
                                Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc, true, false);
 
8572
 
 
8573
                                prepared_value = new LocalTemporary (type);
 
8574
                                prepared_value.Store (ec);
 
8575
                                source.Emit (ec);
 
8576
                                prepared_value.Release (ec);
 
8577
 
 
8578
                                if (leave_copy) {
 
8579
                                        ec.Emit (OpCodes.Dup);
 
8580
                                        temp = new LocalTemporary (Type);
 
8581
                                        temp.Store (ec);
 
8582
                                }
 
8583
                        } else if (leave_copy) {
 
8584
                                temp = new LocalTemporary (Type);
 
8585
                                source.Emit (ec);
 
8586
                                temp.Store (ec);
 
8587
                                value = temp;
 
8588
                        }
 
8589
                        
 
8590
                        if (!prepared)
 
8591
                                arguments.Add (new Argument (value));
 
8592
 
 
8593
                        Invocation.EmitCall (ec, InstanceExpression, Setter, arguments, loc, false, prepared);
 
8594
                        
 
8595
                        if (temp != null) {
 
8596
                                temp.Emit (ec);
 
8597
                                temp.Release (ec);
 
8598
                        }
 
8599
                }
 
8600
 
 
8601
                public override string GetSignatureForError ()
 
8602
                {
 
8603
                        return best_candidate.GetSignatureForError ();
 
8604
                }
 
8605
                
 
8606
                public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source)
 
8607
                {
 
8608
#if STATIC
 
8609
                        throw new NotSupportedException ();
 
8610
#else
 
8611
                        var value = new[] { source.MakeExpression (ctx) };
 
8612
                        var args = Arguments.MakeExpression (arguments, ctx).Concat (value);
 
8613
#if NET_4_0
 
8614
                        return SLE.Expression.Block (
 
8615
                                        SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo (), args),
 
8616
                                        value [0]);
 
8617
#else
 
8618
                        return args.First ();
 
8619
#endif
 
8620
#endif
 
8621
                }
 
8622
 
 
8623
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
8624
                {
 
8625
#if STATIC
 
8626
                        return base.MakeExpression (ctx);
 
8627
#else
 
8628
                        var args = Arguments.MakeExpression (arguments, ctx);
 
8629
                        return SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo (), args);
 
8630
#endif
 
8631
                }
 
8632
 
 
8633
                protected override Expression OverloadResolve (ResolveContext rc, Expression right_side)
 
8634
                {
 
8635
                        if (best_candidate != null)
 
8636
                                return this;
 
8637
 
 
8638
                        eclass = ExprClass.IndexerAccess;
 
8639
 
 
8640
                        bool dynamic;
 
8641
                        arguments.Resolve (rc, out dynamic);
 
8642
 
 
8643
                        if (indexers == null && InstanceExpression.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
8644
                                dynamic = true;
 
8645
                        } else {
 
8646
                                var res = new OverloadResolver (indexers, OverloadResolver.Restrictions.None, loc);
 
8647
                                res.BaseMembersProvider = this;
 
8648
 
 
8649
                                // TODO: Do I need 2 argument sets?
 
8650
                                best_candidate = res.ResolveMember<IndexerSpec> (rc, ref arguments);
 
8651
                                if (best_candidate != null)
 
8652
                                        type = res.BestCandidateReturnType;
 
8653
                                else if (!res.BestCandidateIsDynamic)
 
8654
                                        return null;
 
8655
                        }
 
8656
 
 
8657
                        //
 
8658
                        // It has dynamic arguments
 
8659
                        //
 
8660
                        if (dynamic) {
 
8661
                                Arguments args = new Arguments (arguments.Count + 1);
 
8662
                                if (IsBase) {
 
8663
                                        rc.Report.Error (1972, loc,
 
8664
                                                "The indexer base access cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access");
 
8665
                                } else {
 
8666
                                        args.Add (new Argument (InstanceExpression));
 
8667
                                }
 
8668
                                args.AddRange (arguments);
 
8669
 
 
8670
                                best_candidate = null;
 
8671
                                return new DynamicIndexBinder (args, loc);
 
8672
                        }
 
8673
 
 
8674
                        ResolveInstanceExpression (rc, right_side);
 
8675
                        CheckProtectedMemberAccess (rc, best_candidate);
 
8676
                        return this;
 
8677
                }
 
8678
 
 
8679
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
8680
                {
 
8681
                        IndexerExpr target = (IndexerExpr) t;
 
8682
 
 
8683
                        if (arguments != null)
 
8684
                                target.arguments = arguments.Clone (clonectx);
 
8685
                }
 
8686
 
 
8687
                public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
 
8688
                {
 
8689
                        Error_TypeArgumentsCannotBeUsed (ec, "indexer", GetSignatureForError (), loc);
 
8690
                }
 
8691
 
 
8692
                #region IBaseMembersProvider Members
 
8693
 
 
8694
                IList<MemberSpec> OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType)
 
8695
                {
 
8696
                        return baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false);
 
8697
                }
 
8698
 
 
8699
                IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member)
 
8700
                {
 
8701
                        if (queried_type == member.DeclaringType)
 
8702
                                return null;
 
8703
 
 
8704
                        var filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, ((IndexerSpec) member).Parameters, null);
 
8705
                        return MemberCache.FindMember (queried_type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember;
 
8706
                }
 
8707
 
 
8708
                MethodGroupExpr OverloadResolver.IBaseMembersProvider.LookupExtensionMethod (ResolveContext rc)
 
8709
                {
 
8710
                        return null;
 
8711
                }
 
8712
 
 
8713
                #endregion
 
8714
        }
 
8715
 
 
8716
        //
 
8717
        // A base access expression
 
8718
        //
 
8719
        public class BaseThis : This
 
8720
        {
 
8721
                public BaseThis (Location loc)
 
8722
                        : base (loc)
 
8723
                {
 
8724
                }
 
8725
 
 
8726
                public BaseThis (TypeSpec type, Location loc)
 
8727
                        : base (loc)
 
8728
                {
 
8729
                        this.type = type;
 
8730
                        eclass = ExprClass.Variable;
 
8731
                }
 
8732
 
 
8733
                #region Properties
 
8734
 
 
8735
                public override string Name {
 
8736
                        get {
 
8737
                                return "base";
 
8738
                        }
 
8739
                }
 
8740
 
 
8741
                #endregion
 
8742
 
 
8743
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8744
                {
 
8745
                        ec.Report.Error (831, loc, "An expression tree may not contain a base access");
 
8746
                        return base.CreateExpressionTree (ec);
 
8747
                }
 
8748
 
 
8749
                public override void Emit (EmitContext ec)
 
8750
                {
 
8751
                        base.Emit (ec);
 
8752
 
 
8753
                        var context_type = ec.CurrentType;
 
8754
                        if (context_type.IsStruct) {
 
8755
                                ec.Emit (OpCodes.Ldobj, context_type);
 
8756
                                ec.Emit (OpCodes.Box, context_type);
 
8757
                        }
 
8758
                }
 
8759
 
 
8760
                protected override void Error_ThisNotAvailable (ResolveContext ec)
 
8761
                {
 
8762
                        if (ec.IsStatic) {
 
8763
                                ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method");
 
8764
                        } else {
 
8765
                                ec.Report.Error (1512, loc, "Keyword `base' is not available in the current context");
 
8766
                        }
 
8767
                }
 
8768
 
 
8769
                public override void ResolveBase (ResolveContext ec)
 
8770
                {
 
8771
                        base.ResolveBase (ec);
 
8772
                        type = ec.CurrentType.BaseType;
 
8773
                }
 
8774
 
 
8775
                public override object Accept (StructuralVisitor visitor)
 
8776
                {
 
8777
                        return visitor.Visit (this);
 
8778
                }
 
8779
        }
 
8780
 
 
8781
        /// <summary>
 
8782
        ///   This class exists solely to pass the Type around and to be a dummy
 
8783
        ///   that can be passed to the conversion functions (this is used by
 
8784
        ///   foreach implementation to typecast the object return value from
 
8785
        ///   get_Current into the proper type.  All code has been generated and
 
8786
        ///   we only care about the side effect conversions to be performed
 
8787
        ///
 
8788
        ///   This is also now used as a placeholder where a no-action expression
 
8789
        ///   is needed (the `New' class).
 
8790
        /// </summary>
 
8791
        class EmptyExpression : Expression
 
8792
        {
 
8793
                sealed class OutAccessExpression : EmptyExpression
 
8794
                {
 
8795
                        public OutAccessExpression (TypeSpec t)
 
8796
                                : base (t)
 
8797
                        {
 
8798
                        }
 
8799
 
 
8800
                        public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
 
8801
                        {
 
8802
                                rc.Report.Error (206, right_side.Location,
 
8803
                                        "A property, indexer or dynamic member access may not be passed as `ref' or `out' parameter");
 
8804
 
 
8805
                                return null;
 
8806
                        }
 
8807
                }
 
8808
 
 
8809
                public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (InternalType.FakeInternalType);
 
8810
                public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression (InternalType.FakeInternalType);
 
8811
                public static readonly EmptyExpression UnaryAddress = new EmptyExpression (InternalType.FakeInternalType);
 
8812
                public static readonly EmptyExpression EventAddition = new EmptyExpression (InternalType.FakeInternalType);
 
8813
                public static readonly EmptyExpression EventSubtraction = new EmptyExpression (InternalType.FakeInternalType);
 
8814
                public static readonly EmptyExpression MissingValue = new EmptyExpression (InternalType.FakeInternalType);
 
8815
                public static readonly Expression Null = new EmptyExpression (InternalType.FakeInternalType);
 
8816
                public static readonly EmptyExpression OutAccess = new OutAccessExpression (InternalType.FakeInternalType);
 
8817
 
 
8818
                public EmptyExpression (TypeSpec t)
 
8819
                {
 
8820
                        type = t;
 
8821
                        eclass = ExprClass.Value;
 
8822
                        loc = Location.Null;
 
8823
                }
 
8824
 
 
8825
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8826
                {
 
8827
                        throw new NotSupportedException ("ET");
 
8828
                }
 
8829
                
 
8830
                protected override Expression DoResolve (ResolveContext ec)
 
8831
                {
 
8832
                        return this;
 
8833
                }
 
8834
 
 
8835
                public override void Emit (EmitContext ec)
 
8836
                {
 
8837
                        // nothing, as we only exist to not do anything.
 
8838
                }
 
8839
 
 
8840
                public override void EmitSideEffect (EmitContext ec)
 
8841
                {
 
8842
                }
 
8843
        }
 
8844
        
 
8845
        //
 
8846
        // Empty statement expression
 
8847
        //
 
8848
        public sealed class EmptyExpressionStatement : ExpressionStatement
 
8849
        {
 
8850
                public static readonly EmptyExpressionStatement Instance = new EmptyExpressionStatement ();
 
8851
 
 
8852
                private EmptyExpressionStatement ()
 
8853
                {
 
8854
                        loc = Location.Null;
 
8855
                }
 
8856
 
 
8857
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8858
                {
 
8859
                        return null;
 
8860
                }
 
8861
 
 
8862
                public override void EmitStatement (EmitContext ec)
 
8863
                {
 
8864
                        // Do nothing
 
8865
                }
 
8866
 
 
8867
                protected override Expression DoResolve (ResolveContext ec)
 
8868
                {
 
8869
                        eclass = ExprClass.Value;
 
8870
                        type = ec.BuiltinTypes.Object;
 
8871
                        return this;
 
8872
                }
 
8873
 
 
8874
                public override void Emit (EmitContext ec)
 
8875
                {
 
8876
                        // Do nothing
 
8877
                }
 
8878
                
 
8879
                public override object Accept (StructuralVisitor visitor)
 
8880
                {
 
8881
                        return visitor.Visit (this);
 
8882
                }
 
8883
        }
 
8884
 
 
8885
        class ErrorExpression : EmptyExpression
 
8886
        {
 
8887
                public static readonly ErrorExpression Instance = new ErrorExpression ();
 
8888
 
 
8889
                private ErrorExpression ()
 
8890
                        : base (InternalType.FakeInternalType)
 
8891
                {
 
8892
                }
 
8893
 
 
8894
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8895
                {
 
8896
                        return this;
 
8897
                }
 
8898
 
 
8899
                public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
 
8900
                {
 
8901
                        return this;
 
8902
                }
 
8903
 
 
8904
                public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
 
8905
                {
 
8906
                }
 
8907
        }
 
8908
 
 
8909
        public class UserCast : Expression {
 
8910
                MethodSpec method;
 
8911
                Expression source;
 
8912
                
 
8913
                public UserCast (MethodSpec method, Expression source, Location l)
 
8914
                {
 
8915
                        this.method = method;
 
8916
                        this.source = source;
 
8917
                        type = method.ReturnType;
 
8918
                        loc = l;
 
8919
                }
 
8920
 
 
8921
                public Expression Source {
 
8922
                        get {
 
8923
                                return source;
 
8924
                        }
 
8925
                }
 
8926
 
 
8927
                public override Expression CreateExpressionTree (ResolveContext ec)
 
8928
                {
 
8929
                        Arguments args = new Arguments (3);
 
8930
                        args.Add (new Argument (source.CreateExpressionTree (ec)));
 
8931
                        args.Add (new Argument (new TypeOf (type, loc)));
 
8932
                        args.Add (new Argument (new TypeOfMethod (method, loc)));
 
8933
                        return CreateExpressionFactoryCall (ec, "Convert", args);
 
8934
                }
 
8935
                        
 
8936
                protected override Expression DoResolve (ResolveContext ec)
 
8937
                {
 
8938
                        ObsoleteAttribute oa = method.GetAttributeObsolete ();
 
8939
                        if (oa != null)
 
8940
                                AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
 
8941
 
 
8942
                        eclass = ExprClass.Value;
 
8943
                        return this;
 
8944
                }
 
8945
 
 
8946
                public override void Emit (EmitContext ec)
 
8947
                {
 
8948
                        source.Emit (ec);
 
8949
                        ec.Emit (OpCodes.Call, method);
 
8950
                }
 
8951
 
 
8952
                public override string GetSignatureForError ()
 
8953
                {
 
8954
                        return TypeManager.CSharpSignature (method);
 
8955
                }
 
8956
 
 
8957
                public override SLE.Expression MakeExpression (BuilderContext ctx)
 
8958
                {
 
8959
#if STATIC
 
8960
                        return base.MakeExpression (ctx);
 
8961
#else
 
8962
                        return SLE.Expression.Convert (source.MakeExpression (ctx), type.GetMetaInfo (), (MethodInfo) method.GetMetaInfo ());
 
8963
#endif
 
8964
                }
 
8965
        }
 
8966
 
 
8967
        //
 
8968
        // Holds additional type specifiers like ?, *, []
 
8969
        //
 
8970
        public class ComposedTypeSpecifier
 
8971
        {
 
8972
                public static readonly ComposedTypeSpecifier SingleDimension = new ComposedTypeSpecifier (1, Location.Null);
 
8973
 
 
8974
                public readonly int Dimension;
 
8975
                public readonly Location Location;
 
8976
 
 
8977
                public ComposedTypeSpecifier (int specifier, Location loc)
 
8978
                {
 
8979
                        this.Dimension = specifier;
 
8980
                        this.Location = loc;
 
8981
                }
 
8982
 
 
8983
                #region Properties
 
8984
                public bool IsNullable {
 
8985
                        get {
 
8986
                                return Dimension == -1;
 
8987
                        }
 
8988
                }
 
8989
 
 
8990
                public bool IsPointer {
 
8991
                        get {
 
8992
                                return Dimension == -2;
 
8993
                        }
 
8994
                }
 
8995
 
 
8996
                public ComposedTypeSpecifier Next { get; set; }
 
8997
 
 
8998
                #endregion
 
8999
 
 
9000
                public static ComposedTypeSpecifier CreateArrayDimension (int dimension, Location loc)
 
9001
                {
 
9002
                        return new ComposedTypeSpecifier (dimension, loc);
 
9003
                }
 
9004
 
 
9005
                public static ComposedTypeSpecifier CreateNullable (Location loc)
 
9006
                {
 
9007
                        return new ComposedTypeSpecifier (-1, loc);
 
9008
                }
 
9009
 
 
9010
                public static ComposedTypeSpecifier CreatePointer (Location loc)
 
9011
                {
 
9012
                        return new ComposedTypeSpecifier (-2, loc);
 
9013
                }
 
9014
 
 
9015
                public string GetSignatureForError ()
 
9016
                {
 
9017
                        string s =
 
9018
                                IsPointer ? "*" :
 
9019
                                IsNullable ? "?" :
 
9020
                                ArrayContainer.GetPostfixSignature (Dimension);
 
9021
 
 
9022
                        return Next != null ? s + Next.GetSignatureForError () : s;
 
9023
                }
 
9024
        }
 
9025
 
 
9026
        // <summary>
 
9027
        //   This class is used to "construct" the type during a typecast
 
9028
        //   operation.  Since the Type.GetType class in .NET can parse
 
9029
        //   the type specification, we just use this to construct the type
 
9030
        //   one bit at a time.
 
9031
        // </summary>
 
9032
        public class ComposedCast : TypeExpr {
 
9033
                FullNamedExpression left;
 
9034
                ComposedTypeSpecifier spec;
 
9035
 
 
9036
                public FullNamedExpression Left {
 
9037
                        get { return this.left; }
 
9038
                }
 
9039
 
 
9040
                public ComposedTypeSpecifier Spec {
 
9041
                        get {
 
9042
                                return this.spec;
 
9043
                        }
 
9044
                }
 
9045
 
 
9046
                public ComposedCast (FullNamedExpression left, ComposedTypeSpecifier spec)
 
9047
                {
 
9048
                        if (spec == null)
 
9049
                                throw new ArgumentNullException ("spec");
 
9050
 
 
9051
                        this.left = left;
 
9052
                        this.spec = spec;
 
9053
                        this.loc = spec.Location;
 
9054
                }
 
9055
 
 
9056
                public override TypeSpec ResolveAsType (IMemberContext ec)
 
9057
                {
 
9058
                        type = left.ResolveAsType (ec);
 
9059
                        if (type == null)
 
9060
                                return null;
 
9061
 
 
9062
                        eclass = ExprClass.Type;
 
9063
 
 
9064
                        var single_spec = spec;
 
9065
 
 
9066
                        if (single_spec.IsNullable) {
 
9067
                                type = new Nullable.NullableType (type, loc).ResolveAsType (ec);
 
9068
                                if (type == null)
 
9069
                                        return null;
 
9070
 
 
9071
                                single_spec = single_spec.Next;
 
9072
                        } else if (single_spec.IsPointer) {
 
9073
                                if (!TypeManager.VerifyUnmanaged (ec.Module, type, loc))
 
9074
                                        return null;
 
9075
 
 
9076
                                if (!ec.IsUnsafe) {
 
9077
                                        UnsafeError (ec.Module.Compiler.Report, loc);
 
9078
                                }
 
9079
 
 
9080
                                do {
 
9081
                                        type = PointerContainer.MakeType (ec.Module, type);
 
9082
                                        single_spec = single_spec.Next;
 
9083
                                } while (single_spec != null && single_spec.IsPointer);
 
9084
                        }
 
9085
 
 
9086
                        if (single_spec != null && single_spec.Dimension > 0) {
 
9087
                                if (type.IsSpecialRuntimeType) {
 
9088
                                        ec.Module.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ());
 
9089
                                } else if (type.IsStatic) {
 
9090
                                        ec.Module.Compiler.Report.SymbolRelatedToPreviousError (type);
 
9091
                                        ec.Module.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'",
 
9092
                                                type.GetSignatureForError ());
 
9093
                                } else {
 
9094
                                        MakeArray (ec.Module, single_spec);
 
9095
                                }
 
9096
                        }
 
9097
 
 
9098
                        return type;
 
9099
                }
 
9100
 
 
9101
                void MakeArray (ModuleContainer module, ComposedTypeSpecifier spec)
 
9102
                {
 
9103
                        if (spec.Next != null)
 
9104
                                MakeArray (module, spec.Next);
 
9105
 
 
9106
                        type = ArrayContainer.MakeType (module, type, spec.Dimension);
 
9107
                }
 
9108
 
 
9109
                public override string GetSignatureForError ()
 
9110
                {
 
9111
                        return left.GetSignatureForError () + spec.GetSignatureForError ();
 
9112
                }
 
9113
 
 
9114
                public override object Accept (StructuralVisitor visitor)
 
9115
                {
 
9116
                        return visitor.Visit (this);
 
9117
                }
 
9118
        }
 
9119
 
 
9120
        class FixedBufferPtr : Expression
 
9121
        {
 
9122
                readonly Expression array;
 
9123
 
 
9124
                public FixedBufferPtr (Expression array, TypeSpec array_type, Location l)
 
9125
                {
 
9126
                        this.type = array_type;
 
9127
                        this.array = array;
 
9128
                        this.loc = l;
 
9129
                }
 
9130
 
 
9131
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9132
                {
 
9133
                        Error_PointerInsideExpressionTree (ec);
 
9134
                        return null;
 
9135
                }
 
9136
 
 
9137
                public override void Emit(EmitContext ec)
 
9138
                {
 
9139
                        array.Emit (ec);
 
9140
                }
 
9141
 
 
9142
                protected override Expression DoResolve (ResolveContext ec)
 
9143
                {
 
9144
                        type = PointerContainer.MakeType (ec.Module, type);
 
9145
                        eclass = ExprClass.Value;
 
9146
                        return this;
 
9147
                }
 
9148
        }
 
9149
 
 
9150
 
 
9151
        //
 
9152
        // This class is used to represent the address of an array, used
 
9153
        // only by the Fixed statement, this generates "&a [0]" construct
 
9154
        // for fixed (char *pa = a)
 
9155
        //
 
9156
        class ArrayPtr : FixedBufferPtr
 
9157
        {
 
9158
                public ArrayPtr (Expression array, TypeSpec array_type, Location l):
 
9159
                        base (array, array_type, l)
 
9160
                {
 
9161
                }
 
9162
 
 
9163
                public override void Emit (EmitContext ec)
 
9164
                {
 
9165
                        base.Emit (ec);
 
9166
                        
 
9167
                        ec.EmitInt (0);
 
9168
                        ec.Emit (OpCodes.Ldelema, ((PointerContainer) type).Element);
 
9169
                }
 
9170
        }
 
9171
 
 
9172
        //
 
9173
        // Encapsulates a conversion rules required for array indexes
 
9174
        //
 
9175
        public class ArrayIndexCast : TypeCast
 
9176
        {
 
9177
                public ArrayIndexCast (Expression expr, TypeSpec returnType)
 
9178
                        : base (expr, returnType)
 
9179
                {
 
9180
                        if (expr.Type == returnType) // int -> int
 
9181
                                throw new ArgumentException ("unnecessary array index conversion");
 
9182
                }
 
9183
 
 
9184
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9185
                {
 
9186
                        using (ec.Set (ResolveContext.Options.CheckedScope)) {
 
9187
                                return base.CreateExpressionTree (ec);
 
9188
                        }
 
9189
                }
 
9190
 
 
9191
                public override void Emit (EmitContext ec)
 
9192
                {
 
9193
                        child.Emit (ec);
 
9194
 
 
9195
                        switch (child.Type.BuiltinType) {
 
9196
                        case BuiltinTypeSpec.Type.UInt:
 
9197
                                ec.Emit (OpCodes.Conv_U);
 
9198
                                break;
 
9199
                        case BuiltinTypeSpec.Type.Long:
 
9200
                                ec.Emit (OpCodes.Conv_Ovf_I);
 
9201
                                break;
 
9202
                        case BuiltinTypeSpec.Type.ULong:
 
9203
                                ec.Emit (OpCodes.Conv_Ovf_I_Un);
 
9204
                                break;
 
9205
                        default:
 
9206
                                throw new InternalErrorException ("Cannot emit cast to unknown array element type", type);
 
9207
                        }
 
9208
                }
 
9209
        }
 
9210
 
 
9211
        //
 
9212
        // Implements the `stackalloc' keyword
 
9213
        //
 
9214
        public class StackAlloc : Expression {
 
9215
                TypeSpec otype;
 
9216
                Expression t;
 
9217
                Expression count;
 
9218
                
 
9219
                public Expression TypeExpression {
 
9220
                        get { return this.t; }
 
9221
                }
 
9222
 
 
9223
                public Expression CountExpression {
 
9224
                        get { return this.count; }
 
9225
                }
 
9226
                
 
9227
                public StackAlloc (Expression type, Expression count, Location l)
 
9228
                {
 
9229
                        t = type;
 
9230
                        this.count = count;
 
9231
                        loc = l;
 
9232
                }
 
9233
 
 
9234
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9235
                {
 
9236
                        throw new NotSupportedException ("ET");
 
9237
                }
 
9238
 
 
9239
                protected override Expression DoResolve (ResolveContext ec)
 
9240
                {
 
9241
                        count = count.Resolve (ec);
 
9242
                        if (count == null)
 
9243
                                return null;
 
9244
                        
 
9245
                        if (count.Type.BuiltinType != BuiltinTypeSpec.Type.UInt){
 
9246
                                count = Convert.ImplicitConversionRequired (ec, count, ec.BuiltinTypes.Int, loc);
 
9247
                                if (count == null)
 
9248
                                        return null;
 
9249
                        }
 
9250
 
 
9251
                        Constant c = count as Constant;
 
9252
                        if (c != null && c.IsNegative) {
 
9253
                                ec.Report.Error (247, loc, "Cannot use a negative size with stackalloc");
 
9254
                        }
 
9255
 
 
9256
                        if (ec.HasAny (ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) {
 
9257
                                ec.Report.Error (255, loc, "Cannot use stackalloc in finally or catch");
 
9258
                        }
 
9259
 
 
9260
                        otype = t.ResolveAsType (ec);
 
9261
                        if (otype == null)
 
9262
                                return null;
 
9263
 
 
9264
                        if (!TypeManager.VerifyUnmanaged (ec.Module, otype, loc))
 
9265
                                return null;
 
9266
 
 
9267
                        type = PointerContainer.MakeType (ec.Module, otype);
 
9268
                        eclass = ExprClass.Value;
 
9269
 
 
9270
                        return this;
 
9271
                }
 
9272
 
 
9273
                public override void Emit (EmitContext ec)
 
9274
                {
 
9275
                        int size = BuiltinTypeSpec.GetSize (otype);
 
9276
 
 
9277
                        count.Emit (ec);
 
9278
 
 
9279
                        if (size == 0)
 
9280
                                ec.Emit (OpCodes.Sizeof, otype);
 
9281
                        else
 
9282
                                ec.EmitInt (size);
 
9283
 
 
9284
                        ec.Emit (OpCodes.Mul_Ovf_Un);
 
9285
                        ec.Emit (OpCodes.Localloc);
 
9286
                }
 
9287
 
 
9288
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
9289
                {
 
9290
                        StackAlloc target = (StackAlloc) t;
 
9291
                        target.count = count.Clone (clonectx);
 
9292
                        target.t = t.Clone (clonectx);
 
9293
                }
 
9294
                
 
9295
                public override object Accept (StructuralVisitor visitor)
 
9296
                {
 
9297
                        return visitor.Visit (this);
 
9298
                }
 
9299
        }
 
9300
 
 
9301
        //
 
9302
        // An object initializer expression
 
9303
        //
 
9304
        public class ElementInitializer : Assign
 
9305
        {
 
9306
                public readonly string Name;
 
9307
 
 
9308
                public ElementInitializer (string name, Expression initializer, Location loc)
 
9309
                        : base (null, initializer, loc)
 
9310
                {
 
9311
                        this.Name = name;
 
9312
                }
 
9313
                
 
9314
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
9315
                {
 
9316
                        ElementInitializer target = (ElementInitializer) t;
 
9317
                        target.source = source.Clone (clonectx);
 
9318
                }
 
9319
 
 
9320
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9321
                {
 
9322
                        Arguments args = new Arguments (2);
 
9323
                        FieldExpr fe = target as FieldExpr;
 
9324
                        if (fe != null)
 
9325
                                args.Add (new Argument (fe.CreateTypeOfExpression ()));
 
9326
                        else
 
9327
                                args.Add (new Argument (((PropertyExpr)target).CreateSetterTypeOfExpression ()));
 
9328
 
 
9329
                        args.Add (new Argument (source.CreateExpressionTree (ec)));
 
9330
                        return CreateExpressionFactoryCall (ec,
 
9331
                                source is CollectionOrObjectInitializers ? "ListBind" : "Bind",
 
9332
                                args);
 
9333
                }
 
9334
 
 
9335
                protected override Expression DoResolve (ResolveContext ec)
 
9336
                {
 
9337
                        if (source == null)
 
9338
                                return EmptyExpressionStatement.Instance;
 
9339
 
 
9340
                        var t = ec.CurrentInitializerVariable.Type;
 
9341
                        if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
 
9342
                                Arguments args = new Arguments (1);
 
9343
                                args.Add (new Argument (ec.CurrentInitializerVariable));
 
9344
                                target = new DynamicMemberBinder (Name, args, loc);
 
9345
                        } else {
 
9346
 
 
9347
                                var member = MemberLookup (ec, false, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
 
9348
                                if (member == null) {
 
9349
                                        member = Expression.MemberLookup (ec, true, t, Name, 0, MemberLookupRestrictions.ExactArity, loc);
 
9350
 
 
9351
                                        if (member != null) {
 
9352
                                                // TODO: ec.Report.SymbolRelatedToPreviousError (member);
 
9353
                                                ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
 
9354
                                                return null;
 
9355
                                        }
 
9356
                                }
 
9357
 
 
9358
                                if (member == null) {
 
9359
                                        Error_TypeDoesNotContainDefinition (ec, loc, t, Name);
 
9360
                                        return null;
 
9361
                                }
 
9362
 
 
9363
                                if (!(member is PropertyExpr || member is FieldExpr)) {
 
9364
                                        ec.Report.Error (1913, loc,
 
9365
                                                "Member `{0}' cannot be initialized. An object initializer may only be used for fields, or properties",
 
9366
                                                member.GetSignatureForError ());
 
9367
 
 
9368
                                        return null;
 
9369
                                }
 
9370
 
 
9371
                                var me = member as MemberExpr;
 
9372
                                if (me.IsStatic) {
 
9373
                                        ec.Report.Error (1914, loc,
 
9374
                                                "Static field or property `{0}' cannot be assigned in an object initializer",
 
9375
                                                me.GetSignatureForError ());
 
9376
                                }
 
9377
 
 
9378
                                target = me;
 
9379
                                me.InstanceExpression = ec.CurrentInitializerVariable;
 
9380
                        }
 
9381
 
 
9382
                        if (source is CollectionOrObjectInitializers) {
 
9383
                                Expression previous = ec.CurrentInitializerVariable;
 
9384
                                ec.CurrentInitializerVariable = target;
 
9385
                                source = source.Resolve (ec);
 
9386
                                ec.CurrentInitializerVariable = previous;
 
9387
                                if (source == null)
 
9388
                                        return null;
 
9389
                                        
 
9390
                                eclass = source.eclass;
 
9391
                                type = source.Type;
 
9392
                                return this;
 
9393
                        }
 
9394
 
 
9395
                        return base.DoResolve (ec);
 
9396
                }
 
9397
        
 
9398
                public override void EmitStatement (EmitContext ec)
 
9399
                {
 
9400
                        if (source is CollectionOrObjectInitializers)
 
9401
                                source.Emit (ec);
 
9402
                        else
 
9403
                                base.EmitStatement (ec);
 
9404
                }
 
9405
        }
 
9406
        
 
9407
        //
 
9408
        // A collection initializer expression
 
9409
        //
 
9410
        class CollectionElementInitializer : Invocation
 
9411
        {
 
9412
                public class ElementInitializerArgument : Argument
 
9413
                {
 
9414
                        public ElementInitializerArgument (Expression e)
 
9415
                                : base (e)
 
9416
                        {
 
9417
                        }
 
9418
                }
 
9419
 
 
9420
                sealed class AddMemberAccess : MemberAccess
 
9421
                {
 
9422
                        public AddMemberAccess (Expression expr, Location loc)
 
9423
                                : base (expr, "Add", loc)
 
9424
                        {
 
9425
                        }
 
9426
 
 
9427
                        protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
 
9428
                        {
 
9429
                                if (TypeManager.HasElementType (type))
 
9430
                                        return;
 
9431
 
 
9432
                                base.Error_TypeDoesNotContainDefinition (ec, type, name);
 
9433
                        }
 
9434
                }
 
9435
 
 
9436
                public CollectionElementInitializer (Expression argument)
 
9437
                        : base (null, new Arguments (1))
 
9438
                {
 
9439
                        base.arguments.Add (new ElementInitializerArgument (argument));
 
9440
                        this.loc = argument.Location;
 
9441
                }
 
9442
 
 
9443
                public CollectionElementInitializer (List<Expression> arguments, Location loc)
 
9444
                        : base (null, new Arguments (arguments.Count))
 
9445
                {
 
9446
                        foreach (Expression e in arguments)
 
9447
                                base.arguments.Add (new ElementInitializerArgument (e));
 
9448
 
 
9449
                        this.loc = loc;
 
9450
                }
 
9451
 
 
9452
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9453
                {
 
9454
                        Arguments args = new Arguments (2);
 
9455
                        args.Add (new Argument (mg.CreateExpressionTree (ec)));
 
9456
 
 
9457
                        var expr_initializers = new ArrayInitializer (arguments.Count, loc);
 
9458
                        foreach (Argument a in arguments)
 
9459
                                expr_initializers.Add (a.CreateExpressionTree (ec));
 
9460
 
 
9461
                        args.Add (new Argument (new ArrayCreation (
 
9462
                                CreateExpressionTypeExpression (ec, loc), expr_initializers, loc)));
 
9463
                        return CreateExpressionFactoryCall (ec, "ElementInit", args);
 
9464
                }
 
9465
 
 
9466
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
9467
                {
 
9468
                        CollectionElementInitializer target = (CollectionElementInitializer) t;
 
9469
                        if (arguments != null)
 
9470
                                target.arguments = arguments.Clone (clonectx);
 
9471
                }
 
9472
 
 
9473
                protected override Expression DoResolve (ResolveContext ec)
 
9474
                {
 
9475
                        base.expr = new AddMemberAccess (ec.CurrentInitializerVariable, loc);
 
9476
 
 
9477
                        return base.DoResolve (ec);
 
9478
                }
 
9479
        }
 
9480
        
 
9481
        //
 
9482
        // A block of object or collection initializers
 
9483
        //
 
9484
        public class CollectionOrObjectInitializers : ExpressionStatement
 
9485
        {
 
9486
                IList<Expression> initializers;
 
9487
                bool is_collection_initialization;
 
9488
                
 
9489
                public static readonly CollectionOrObjectInitializers Empty = 
 
9490
                        new CollectionOrObjectInitializers (Array.AsReadOnly (new Expression [0]), Location.Null);
 
9491
 
 
9492
                public CollectionOrObjectInitializers (IList<Expression> initializers, Location loc)
 
9493
                {
 
9494
                        this.initializers = initializers;
 
9495
                        this.loc = loc;
 
9496
                }
 
9497
                
 
9498
                public bool IsEmpty {
 
9499
                        get {
 
9500
                                return initializers.Count == 0;
 
9501
                        }
 
9502
                }
 
9503
 
 
9504
                public bool IsCollectionInitializer {
 
9505
                        get {
 
9506
                                return is_collection_initialization;
 
9507
                        }
 
9508
                }
 
9509
 
 
9510
                protected override void CloneTo (CloneContext clonectx, Expression target)
 
9511
                {
 
9512
                        CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target;
 
9513
 
 
9514
                        t.initializers = new List<Expression> (initializers.Count);
 
9515
                        foreach (var e in initializers)
 
9516
                                t.initializers.Add (e.Clone (clonectx));
 
9517
                }
 
9518
 
 
9519
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9520
                {
 
9521
                        var expr_initializers = new ArrayInitializer (initializers.Count, loc);
 
9522
                        foreach (Expression e in initializers) {
 
9523
                                Expression expr = e.CreateExpressionTree (ec);
 
9524
                                if (expr != null)
 
9525
                                        expr_initializers.Add (expr);
 
9526
                        }
 
9527
 
 
9528
                        return new ImplicitlyTypedArrayCreation (expr_initializers, loc);
 
9529
                }
 
9530
                
 
9531
                protected override Expression DoResolve (ResolveContext ec)
 
9532
                {
 
9533
                        List<string> element_names = null;
 
9534
                        for (int i = 0; i < initializers.Count; ++i) {
 
9535
                                Expression initializer = initializers [i];
 
9536
                                ElementInitializer element_initializer = initializer as ElementInitializer;
 
9537
 
 
9538
                                if (i == 0) {
 
9539
                                        if (element_initializer != null) {
 
9540
                                                element_names = new List<string> (initializers.Count);
 
9541
                                                element_names.Add (element_initializer.Name);
 
9542
                                        } else if (initializer is CompletingExpression){
 
9543
                                                initializer.Resolve (ec);
 
9544
                                                throw new InternalErrorException ("This line should never be reached");
 
9545
                                        } else {
 
9546
                                                var t = ec.CurrentInitializerVariable.Type;
 
9547
                                                // LAMESPEC: The collection must implement IEnumerable only, no dynamic support
 
9548
                                                if (!t.ImplementsInterface (ec.BuiltinTypes.IEnumerable, false) && t.BuiltinType != BuiltinTypeSpec.Type.Dynamic) {
 
9549
                                                        ec.Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " +
 
9550
                                                                "object initializer because type `{1}' does not implement `{2}' interface",
 
9551
                                                                ec.CurrentInitializerVariable.GetSignatureForError (),
 
9552
                                                                TypeManager.CSharpName (ec.CurrentInitializerVariable.Type),
 
9553
                                                                TypeManager.CSharpName (ec.BuiltinTypes.IEnumerable));
 
9554
                                                        return null;
 
9555
                                                }
 
9556
                                                is_collection_initialization = true;
 
9557
                                        }
 
9558
                                } else {
 
9559
                                        if (is_collection_initialization != (element_initializer == null)) {
 
9560
                                                ec.Report.Error (747, initializer.Location, "Inconsistent `{0}' member declaration",
 
9561
                                                        is_collection_initialization ? "collection initializer" : "object initializer");
 
9562
                                                continue;
 
9563
                                        }
 
9564
 
 
9565
                                        if (!is_collection_initialization) {
 
9566
                                                if (element_names.Contains (element_initializer.Name)) {
 
9567
                                                        ec.Report.Error (1912, element_initializer.Location,
 
9568
                                                                "An object initializer includes more than one member `{0}' initialization",
 
9569
                                                                element_initializer.Name);
 
9570
                                                } else {
 
9571
                                                        element_names.Add (element_initializer.Name);
 
9572
                                                }
 
9573
                                        }
 
9574
                                }
 
9575
 
 
9576
                                Expression e = initializer.Resolve (ec);
 
9577
                                if (e == EmptyExpressionStatement.Instance)
 
9578
                                        initializers.RemoveAt (i--);
 
9579
                                else
 
9580
                                        initializers [i] = e;
 
9581
                        }
 
9582
 
 
9583
                        type = ec.CurrentInitializerVariable.Type;
 
9584
                        if (is_collection_initialization) {
 
9585
                                if (TypeManager.HasElementType (type)) {
 
9586
                                        ec.Report.Error (1925, loc, "Cannot initialize object of type `{0}' with a collection initializer",
 
9587
                                                TypeManager.CSharpName (type));
 
9588
                                }
 
9589
                        }
 
9590
 
 
9591
                        eclass = ExprClass.Variable;
 
9592
                        return this;
 
9593
                }
 
9594
 
 
9595
                public override void Emit (EmitContext ec)
 
9596
                {
 
9597
                        EmitStatement (ec);
 
9598
                }
 
9599
 
 
9600
                public override void EmitStatement (EmitContext ec)
 
9601
                {
 
9602
                        foreach (ExpressionStatement e in initializers)
 
9603
                                e.EmitStatement (ec);
 
9604
                }
 
9605
        }
 
9606
        
 
9607
        //
 
9608
        // New expression with element/object initializers
 
9609
        //
 
9610
        public class NewInitialize : New
 
9611
        {
 
9612
                //
 
9613
                // This class serves as a proxy for variable initializer target instances.
 
9614
                // A real variable is assigned later when we resolve left side of an
 
9615
                // assignment
 
9616
                //
 
9617
                sealed class InitializerTargetExpression : Expression, IMemoryLocation
 
9618
                {
 
9619
                        NewInitialize new_instance;
 
9620
 
 
9621
                        public InitializerTargetExpression (NewInitialize newInstance)
 
9622
                        {
 
9623
                                this.type = newInstance.type;
 
9624
                                this.loc = newInstance.loc;
 
9625
                                this.eclass = newInstance.eclass;
 
9626
                                this.new_instance = newInstance;
 
9627
                        }
 
9628
 
 
9629
                        public override Expression CreateExpressionTree (ResolveContext ec)
 
9630
                        {
 
9631
                                // Should not be reached
 
9632
                                throw new NotSupportedException ("ET");
 
9633
                        }
 
9634
 
 
9635
                        protected override Expression DoResolve (ResolveContext ec)
 
9636
                        {
 
9637
                                return this;
 
9638
                        }
 
9639
 
 
9640
                        public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
 
9641
                        {
 
9642
                                return this;
 
9643
                        }
 
9644
 
 
9645
                        public override void Emit (EmitContext ec)
 
9646
                        {
 
9647
                                Expression e = (Expression) new_instance.instance;
 
9648
                                e.Emit (ec);
 
9649
                        }
 
9650
 
 
9651
                        #region IMemoryLocation Members
 
9652
 
 
9653
                        public void AddressOf (EmitContext ec, AddressOp mode)
 
9654
                        {
 
9655
                                new_instance.instance.AddressOf (ec, mode);
 
9656
                        }
 
9657
 
 
9658
                        #endregion
 
9659
                }
 
9660
 
 
9661
                CollectionOrObjectInitializers initializers;
 
9662
                IMemoryLocation instance;
 
9663
 
 
9664
                public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l)
 
9665
                        : base (requested_type, arguments, l)
 
9666
                {
 
9667
                        this.initializers = initializers;
 
9668
                }
 
9669
 
 
9670
                protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode)
 
9671
                {
 
9672
                        instance = base.EmitAddressOf (ec, Mode);
 
9673
 
 
9674
                        if (!initializers.IsEmpty)
 
9675
                                initializers.Emit (ec);
 
9676
 
 
9677
                        return instance;
 
9678
                }
 
9679
 
 
9680
                protected override void CloneTo (CloneContext clonectx, Expression t)
 
9681
                {
 
9682
                        base.CloneTo (clonectx, t);
 
9683
 
 
9684
                        NewInitialize target = (NewInitialize) t;
 
9685
                        target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx);
 
9686
                }
 
9687
 
 
9688
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9689
                {
 
9690
                        Arguments args = new Arguments (2);
 
9691
                        args.Add (new Argument (base.CreateExpressionTree (ec)));
 
9692
                        if (!initializers.IsEmpty)
 
9693
                                args.Add (new Argument (initializers.CreateExpressionTree (ec)));
 
9694
 
 
9695
                        return CreateExpressionFactoryCall (ec,
 
9696
                                initializers.IsCollectionInitializer ? "ListInit" : "MemberInit",
 
9697
                                args);
 
9698
                }
 
9699
 
 
9700
                protected override Expression DoResolve (ResolveContext ec)
 
9701
                {
 
9702
                        Expression e = base.DoResolve (ec);
 
9703
                        if (type == null)
 
9704
                                return null;
 
9705
 
 
9706
                        Expression previous = ec.CurrentInitializerVariable;
 
9707
                        ec.CurrentInitializerVariable = new InitializerTargetExpression (this);
 
9708
                        initializers.Resolve (ec);
 
9709
                        ec.CurrentInitializerVariable = previous;
 
9710
                        return e;
 
9711
                }
 
9712
 
 
9713
                public override bool Emit (EmitContext ec, IMemoryLocation target)
 
9714
                {
 
9715
                        bool left_on_stack = base.Emit (ec, target);
 
9716
 
 
9717
                        if (initializers.IsEmpty)
 
9718
                                return left_on_stack;
 
9719
 
 
9720
                        LocalTemporary temp = target as LocalTemporary;
 
9721
                        if (temp == null) {
 
9722
                                if (!left_on_stack) {
 
9723
                                        VariableReference vr = target as VariableReference;
 
9724
                                        
 
9725
                                        // FIXME: This still does not work correctly for pre-set variables
 
9726
                                        if (vr != null && vr.IsRef)
 
9727
                                                target.AddressOf (ec, AddressOp.Load);
 
9728
 
 
9729
                                        ((Expression) target).Emit (ec);
 
9730
                                        left_on_stack = true;
 
9731
                                }
 
9732
 
 
9733
                                temp = new LocalTemporary (type);
 
9734
                        }
 
9735
 
 
9736
                        instance = temp;
 
9737
                        if (left_on_stack)
 
9738
                                temp.Store (ec);
 
9739
 
 
9740
                        initializers.Emit (ec);
 
9741
 
 
9742
                        if (left_on_stack) {
 
9743
                                temp.Emit (ec);
 
9744
                                temp.Release (ec);
 
9745
                        }
 
9746
 
 
9747
                        return left_on_stack;
 
9748
                }
 
9749
 
 
9750
                public override object Accept (StructuralVisitor visitor)
 
9751
                {
 
9752
                        return visitor.Visit (this);
 
9753
                }
 
9754
        }
 
9755
 
 
9756
        public class NewAnonymousType : New
 
9757
        {
 
9758
                static readonly AnonymousTypeParameter[] EmptyParameters = new AnonymousTypeParameter[0];
 
9759
 
 
9760
                List<AnonymousTypeParameter> parameters;
 
9761
                readonly TypeContainer parent;
 
9762
                AnonymousTypeClass anonymous_type;
 
9763
 
 
9764
                public List<AnonymousTypeParameter> Parameters {
 
9765
                        get { return this.parameters; }
 
9766
                }
 
9767
 
 
9768
                public NewAnonymousType (List<AnonymousTypeParameter> parameters, TypeContainer parent, Location loc)
 
9769
                         : base (null, null, loc)
 
9770
                {
 
9771
                        this.parameters = parameters;
 
9772
                        this.parent = parent;
 
9773
                }
 
9774
 
 
9775
                protected override void CloneTo (CloneContext clonectx, Expression target)
 
9776
                {
 
9777
                        if (parameters == null)
 
9778
                                return;
 
9779
 
 
9780
                        NewAnonymousType t = (NewAnonymousType) target;
 
9781
                        t.parameters = new List<AnonymousTypeParameter> (parameters.Count);
 
9782
                        foreach (AnonymousTypeParameter atp in parameters)
 
9783
                                t.parameters.Add ((AnonymousTypeParameter) atp.Clone (clonectx));
 
9784
                }
 
9785
 
 
9786
                AnonymousTypeClass CreateAnonymousType (ResolveContext ec, IList<AnonymousTypeParameter> parameters)
 
9787
                {
 
9788
                        AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters);
 
9789
                        if (type != null)
 
9790
                                return type;
 
9791
 
 
9792
                        type = AnonymousTypeClass.Create (parent, parameters, loc);
 
9793
                        if (type == null)
 
9794
                                return null;
 
9795
 
 
9796
                        type.CreateType ();
 
9797
                        type.DefineType ();
 
9798
                        type.ResolveTypeParameters ();
 
9799
                        type.Define ();
 
9800
                        type.EmitType ();
 
9801
                        if (ec.Report.Errors == 0)
 
9802
                                type.CloseType ();
 
9803
 
 
9804
                        parent.Module.AddAnonymousType (type);
 
9805
                        return type;
 
9806
                }
 
9807
 
 
9808
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9809
                {
 
9810
                        if (parameters == null)
 
9811
                                return base.CreateExpressionTree (ec);
 
9812
 
 
9813
                        var init = new ArrayInitializer (parameters.Count, loc);
 
9814
                        foreach (Property p in anonymous_type.Properties)
 
9815
                                init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc));
 
9816
 
 
9817
                        var ctor_args = new ArrayInitializer (arguments.Count, loc);
 
9818
                        foreach (Argument a in arguments)
 
9819
                                ctor_args.Add (a.CreateExpressionTree (ec));
 
9820
 
 
9821
                        Arguments args = new Arguments (3);
 
9822
                        args.Add (new Argument (new TypeOfMethod (method, loc)));
 
9823
                        args.Add (new Argument (new ArrayCreation (CreateExpressionTypeExpression (ec, loc), ctor_args, loc)));
 
9824
                        args.Add (new Argument (new ImplicitlyTypedArrayCreation (init, loc)));
 
9825
 
 
9826
                        return CreateExpressionFactoryCall (ec, "New", args);
 
9827
                }
 
9828
 
 
9829
                protected override Expression DoResolve (ResolveContext ec)
 
9830
                {
 
9831
                        if (ec.HasSet (ResolveContext.Options.ConstantScope)) {
 
9832
                                ec.Report.Error (836, loc, "Anonymous types cannot be used in this expression");
 
9833
                                return null;
 
9834
                        }
 
9835
 
 
9836
                        if (parameters == null) {
 
9837
                                anonymous_type = CreateAnonymousType (ec, EmptyParameters);
 
9838
                                RequestedType = new TypeExpression (anonymous_type.Definition, loc);
 
9839
                                return base.DoResolve (ec);
 
9840
                        }
 
9841
 
 
9842
                        bool error = false;
 
9843
                        arguments = new Arguments (parameters.Count);
 
9844
                        TypeExpression [] t_args = new TypeExpression [parameters.Count];
 
9845
                        for (int i = 0; i < parameters.Count; ++i) {
 
9846
                                Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec);
 
9847
                                if (e == null) {
 
9848
                                        error = true;
 
9849
                                        continue;
 
9850
                                }
 
9851
 
 
9852
                                arguments.Add (new Argument (e));
 
9853
                                t_args [i] = new TypeExpression (e.Type, e.Location);
 
9854
                        }
 
9855
 
 
9856
                        if (error)
 
9857
                                return null;
 
9858
 
 
9859
                        anonymous_type = CreateAnonymousType (ec, parameters);
 
9860
                        if (anonymous_type == null)
 
9861
                                return null;
 
9862
 
 
9863
                        RequestedType = new GenericTypeExpr (anonymous_type.Definition, new TypeArguments (t_args), loc);
 
9864
                        return base.DoResolve (ec);
 
9865
                }
 
9866
                
 
9867
                public override object Accept (StructuralVisitor visitor)
 
9868
                {
 
9869
                        return visitor.Visit (this);
 
9870
                }
 
9871
        }
 
9872
 
 
9873
        public class AnonymousTypeParameter : ShimExpression
 
9874
        {
 
9875
                public readonly string Name;
 
9876
 
 
9877
                public AnonymousTypeParameter (Expression initializer, string name, Location loc)
 
9878
                        : base (initializer)
 
9879
                {
 
9880
                        this.Name = name;
 
9881
                        this.loc = loc;
 
9882
                }
 
9883
                
 
9884
                public AnonymousTypeParameter (Parameter parameter)
 
9885
                        : base (new SimpleName (parameter.Name, parameter.Location))
 
9886
                {
 
9887
                        this.Name = parameter.Name;
 
9888
                        this.loc = parameter.Location;
 
9889
                }               
 
9890
 
 
9891
                public override bool Equals (object o)
 
9892
                {
 
9893
                        AnonymousTypeParameter other = o as AnonymousTypeParameter;
 
9894
                        return other != null && Name == other.Name;
 
9895
                }
 
9896
 
 
9897
                public override int GetHashCode ()
 
9898
                {
 
9899
                        return Name.GetHashCode ();
 
9900
                }
 
9901
 
 
9902
                protected override Expression DoResolve (ResolveContext ec)
 
9903
                {
 
9904
                        Expression e = expr.Resolve (ec);
 
9905
                        if (e == null)
 
9906
                                return null;
 
9907
 
 
9908
                        if (e.eclass == ExprClass.MethodGroup) {
 
9909
                                Error_InvalidInitializer (ec, e.ExprClassName);
 
9910
                                return null;
 
9911
                        }
 
9912
 
 
9913
                        type = e.Type;
 
9914
                        if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) {
 
9915
                                Error_InvalidInitializer (ec, e.GetSignatureForError ());
 
9916
                                return null;
 
9917
                        }
 
9918
 
 
9919
                        return e;
 
9920
                }
 
9921
 
 
9922
                protected virtual void Error_InvalidInitializer (ResolveContext ec, string initializer)
 
9923
                {
 
9924
                        ec.Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'",
 
9925
                                Name, initializer);
 
9926
                }
 
9927
        }
 
9928
 
 
9929
        class Await : ExpressionStatement
 
9930
        {
 
9931
                Expression expr;
 
9932
 
 
9933
                public Await (Expression expr, Location loc)
 
9934
                {
 
9935
                        this.expr = expr;
 
9936
                        this.loc = loc;
 
9937
                }
 
9938
 
 
9939
                public override Expression CreateExpressionTree (ResolveContext ec)
 
9940
                {
 
9941
                        throw new NotImplementedException ();
 
9942
                }
 
9943
 
 
9944
                public override void Emit (EmitContext ec)
 
9945
                {
 
9946
                        throw new NotImplementedException ();
 
9947
                }
 
9948
 
 
9949
                public override void EmitStatement (EmitContext ec)
 
9950
                {
 
9951
                        throw new NotImplementedException ();
 
9952
                }
 
9953
 
 
9954
                protected override Expression DoResolve (ResolveContext rc)
 
9955
                {
 
9956
                        expr = expr.Resolve (rc);
 
9957
                        if (expr == null)
 
9958
                                return null;
 
9959
 
 
9960
//                      Iterator.CreateIterator
 
9961
 
 
9962
                        type = expr.Type;
 
9963
                        eclass = expr.eclass;
 
9964
                        return this;
 
9965
                }
 
9966
        }
 
9967
}