* XmlTypeAttribute.cs: added property AnonymousType for 2.0
[mono.git] / mcs / mcs / ecore.cs
1 //
2 // ecore.cs: Core of the Expression representation for the intermediate tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //   Marek Safar (marek.safar@seznam.cz)
7 //
8 // (C) 2001, 2002, 2003 Ximian, Inc.
9 //
10 //
11
12 namespace Mono.CSharp {
13         using System;
14         using System.Collections;
15         using System.Diagnostics;
16         using System.Reflection;
17         using System.Reflection.Emit;
18         using System.Text;
19
20         /// <remarks>
21         ///   The ExprClass class contains the is used to pass the 
22         ///   classification of an expression (value, variable, namespace,
23         ///   type, method group, property access, event access, indexer access,
24         ///   nothing).
25         /// </remarks>
26         public enum ExprClass : byte {
27                 Invalid,
28                 
29                 Value,
30                 Variable,
31                 Namespace,
32                 Type,
33                 MethodGroup,
34                 PropertyAccess,
35                 EventAccess,
36                 IndexerAccess,
37                 Nothing, 
38         }
39
40         /// <remarks>
41         ///   This is used to tell Resolve in which types of expressions we're
42         ///   interested.
43         /// </remarks>
44         [Flags]
45         public enum ResolveFlags {
46                 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
47                 VariableOrValue         = 1,
48
49                 // Returns a type expression.
50                 Type                    = 2,
51
52                 // Returns a method group.
53                 MethodGroup             = 4,
54
55                 // Mask of all the expression class flags.
56                 MaskExprClass           = 7,
57
58                 // Disable control flow analysis while resolving the expression.
59                 // This is used when resolving the instance expression of a field expression.
60                 DisableFlowAnalysis     = 8,
61
62                 // Set if this is resolving the first part of a MemberAccess.
63                 Intermediate            = 16,
64
65                 // Disable control flow analysis _of struct_ while resolving the expression.
66                 // This is used when resolving the instance expression of a field expression.
67                 DisableStructFlowAnalysis       = 32,
68
69         }
70
71         //
72         // This is just as a hint to AddressOf of what will be done with the
73         // address.
74         [Flags]
75         public enum AddressOp {
76                 Store = 1,
77                 Load  = 2,
78                 LoadStore = 3
79         };
80         
81         /// <summary>
82         ///   This interface is implemented by variables
83         /// </summary>
84         public interface IMemoryLocation {
85                 /// <summary>
86                 ///   The AddressOf method should generate code that loads
87                 ///   the address of the object and leaves it on the stack.
88                 ///
89                 ///   The `mode' argument is used to notify the expression
90                 ///   of whether this will be used to read from the address or
91                 ///   write to the address.
92                 ///
93                 ///   This is just a hint that can be used to provide good error
94                 ///   reporting, and should have no other side effects. 
95                 /// </summary>
96                 void AddressOf (EmitContext ec, AddressOp mode);
97         }
98
99         /// <summary>
100         ///   This interface is implemented by variables
101         /// </summary>
102         public interface IVariable {
103                 VariableInfo VariableInfo {
104                         get;
105                 }
106
107                 bool VerifyFixed ();
108         }
109
110         /// <remarks>
111         ///   Base class for expressions
112         /// </remarks>
113         public abstract class Expression {
114                 public ExprClass eclass;
115                 protected Type type;
116                 protected Location loc;
117                 
118                 public Type Type {
119                         get { return type; }
120                         set { type = value; }
121                 }
122
123                 public virtual Location Location {
124                         get { return loc; }
125                 }
126
127                 /// <summary>
128                 ///   Utility wrapper routine for Error, just to beautify the code
129                 /// </summary>
130                 public void Error (int error, string s)
131                 {
132                         Report.Error (error, loc, s);
133                 }
134
135                 // Not nice but we have broken hierarchy.
136                 public virtual void CheckMarshalByRefAccess ()
137                 {
138                 }
139
140                 public virtual bool GetAttributableValue (Type valueType, out object value)
141                 {
142                         Attribute.Error_AttributeArgumentNotValid (loc);
143                         value = null;
144                         return false;
145                 }
146
147                 public virtual string GetSignatureForError ()
148                 {
149                         return TypeManager.CSharpName (type);
150                 }
151
152                 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
153                 {
154                         MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
155
156                         must_do_cs1540_check = false; // by default we do not check for this
157
158                         //
159                         // If only accessible to the current class or children
160                         //
161                         if (ma == MethodAttributes.Private)
162                                 return invocation_type == mi.DeclaringType ||
163                                         TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
164
165                         if (mi.DeclaringType.Assembly == invocation_type.Assembly) {
166                                 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
167                                         return true;
168                         } else {
169                                 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
170                                         return false;
171                         }
172
173                         // Family and FamANDAssem require that we derive.
174                         // FamORAssem requires that we derive if in different assemblies.
175                         if (ma == MethodAttributes.Family ||
176                             ma == MethodAttributes.FamANDAssem ||
177                             ma == MethodAttributes.FamORAssem) {
178                                 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
179                                         return false;
180
181                                 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
182                                         must_do_cs1540_check = true;
183
184                                 return true;
185                         }
186
187                         return true;
188                 }
189
190                 /// <summary>
191                 ///   Performs semantic analysis on the Expression
192                 /// </summary>
193                 ///
194                 /// <remarks>
195                 ///   The Resolve method is invoked to perform the semantic analysis
196                 ///   on the node.
197                 ///
198                 ///   The return value is an expression (it can be the
199                 ///   same expression in some cases) or a new
200                 ///   expression that better represents this node.
201                 ///   
202                 ///   For example, optimizations of Unary (LiteralInt)
203                 ///   would return a new LiteralInt with a negated
204                 ///   value.
205                 ///   
206                 ///   If there is an error during semantic analysis,
207                 ///   then an error should be reported (using Report)
208                 ///   and a null value should be returned.
209                 ///   
210                 ///   There are two side effects expected from calling
211                 ///   Resolve(): the the field variable "eclass" should
212                 ///   be set to any value of the enumeration
213                 ///   `ExprClass' and the type variable should be set
214                 ///   to a valid type (this is the type of the
215                 ///   expression).
216                 /// </remarks>
217                 public abstract Expression DoResolve (EmitContext ec);
218
219                 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
220                 {
221                         return null;
222                 }
223
224                 //
225                 // This is used if the expression should be resolved as a type or namespace name.
226                 // the default implementation fails.   
227                 //
228                 public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec,  bool silent)
229                 {
230                         return null;
231                 }
232
233                 //
234                 // This is used to resolve the expression as a type, a null
235                 // value will be returned if the expression is not a type
236                 // reference
237                 //
238                 public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
239                 {
240                         TypeExpr te = ResolveAsBaseTerminal (ec, silent);
241                         if (te == null)
242                                 return null;
243
244                         ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
245                         if (obsolete_attr != null && !ec.IsInObsoleteScope) {
246                                 AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location);
247                         }
248                         return te;
249                 }
250
251                 public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent)
252                 {
253                         int errors = Report.Errors;
254
255                         FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
256
257                         if (fne == null){
258                                 if (!silent && errors == Report.Errors)
259                                         Report.Error (118, loc, "Expecting a type.");
260                                 return null;
261                         }
262
263                         if (fne.eclass != ExprClass.Type) {
264                                 if (!silent && errors == Report.Errors)
265                                         fne.Error_UnexpectedKind (null, "type", loc);
266                                 return null;
267                         }
268
269                         TypeExpr te = fne as TypeExpr;
270
271                         if (!te.CheckAccessLevel (ec.DeclContainer)) {
272                                 Report.SymbolRelatedToPreviousError (te.Type);
273                                 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
274                                 return null;
275                         }
276
277                         te.loc = loc;
278                         return te;
279                 }
280
281                 public static void ErrorIsInaccesible (Location loc, string name)
282                 {
283                         Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
284                 }
285
286                 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
287                 {
288                         Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
289                                 + " the qualifier must be of type `{2}' (or derived from it)", 
290                                 TypeManager.GetFullNameSignature (m),
291                                 TypeManager.CSharpName (qualifier),
292                                 TypeManager.CSharpName (container));
293
294                 }
295
296                 protected void Error_CannotAssign (string to, string roContext)
297                 {
298                         Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'",
299                                 to, roContext);
300                 }
301
302                 public static void Error_VoidInvalidInTheContext (Location loc)
303                 {
304                         Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
305                 }
306
307                 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
308                 {
309                         if (Type.Name == target.Name){
310                                 Report.ExtraInformation (loc,
311                                         String.Format (
312                                         "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
313                                         Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
314                                                          
315                         }
316
317                         if (expl) {
318                                 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
319                                         GetSignatureForError (), TypeManager.CSharpName (target));
320                                 return;
321                         }
322                         
323                         Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
324                         bool b = Convert.ExplicitNumericConversion (e, target) != null;
325
326                         if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
327                                 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
328                                         TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
329                                 return;
330                         }
331
332                         if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
333                                 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
334                                         GetSignatureForError (), TypeManager.CSharpName (target));
335                                 return;
336                         }
337
338                         Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
339                                 Type == TypeManager.anonymous_method_type ?
340                                 "anonymous method" : "`" + GetSignatureForError () + "'",
341                                 TypeManager.CSharpName (target));
342                 }
343
344                 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
345                 {
346                         Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
347                                 TypeManager.CSharpName (type), name);
348                 }
349
350                 ResolveFlags ExprClassToResolveFlags
351                 {
352                         get {
353                                 switch (eclass) {
354                                         case ExprClass.Type:
355                                         case ExprClass.Namespace:
356                                                 return ResolveFlags.Type;
357
358                                         case ExprClass.MethodGroup:
359                                                 return ResolveFlags.MethodGroup;
360
361                                         case ExprClass.Value:
362                                         case ExprClass.Variable:
363                                         case ExprClass.PropertyAccess:
364                                         case ExprClass.EventAccess:
365                                         case ExprClass.IndexerAccess:
366                                                 return ResolveFlags.VariableOrValue;
367
368                                         default:
369                                                 throw new Exception ("Expression " + GetType () +
370                                                         " ExprClass is Invalid after resolve");
371                                 }
372                         }
373                 }
374                
375                 /// <summary>
376                 ///   Resolves an expression and performs semantic analysis on it.
377                 /// </summary>
378                 ///
379                 /// <remarks>
380                 ///   Currently Resolve wraps DoResolve to perform sanity
381                 ///   checking and assertion checking on what we expect from Resolve.
382                 /// </remarks>
383                 public Expression Resolve (EmitContext ec, ResolveFlags flags)
384                 {
385                         if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) 
386                                 return ResolveAsTypeStep (ec, false);
387
388                         bool do_flow_analysis = ec.DoFlowAnalysis;
389                         bool omit_struct_analysis = ec.OmitStructFlowAnalysis;
390                         if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
391                                 do_flow_analysis = false;
392                         if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
393                                 omit_struct_analysis = true;
394
395                         Expression e;
396                         using (ec.WithFlowAnalysis (do_flow_analysis, omit_struct_analysis)) {
397                                 if (this is SimpleName) {
398                                         bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
399                                         e = ((SimpleName) this).DoResolve (ec, intermediate);
400                                 } else {
401                                         e = DoResolve (ec);
402                                 }
403                         }
404
405                         if (e == null)
406                                 return null;
407
408                         if ((flags & e.ExprClassToResolveFlags) == 0) {
409                                 e.Error_UnexpectedKind (flags, loc);
410                                 return null;
411                         }
412
413                         if (e.type == null && !(e is Namespace)) {
414                                 throw new Exception (
415                                         "Expression " + e.GetType () +
416                                         " did not set its type after Resolve\n" +
417                                         "called from: " + this.GetType ());
418                         }
419
420                         return e;
421                 }
422
423                 /// <summary>
424                 ///   Resolves an expression and performs semantic analysis on it.
425                 /// </summary>
426                 public Expression Resolve (EmitContext ec)
427                 {
428                         Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
429
430                         if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
431                                 ((MethodGroupExpr) e).ReportUsageError ();
432                                 return null;
433                         }
434                         return e;
435                 }
436
437                 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
438                 {
439                         Expression e = Resolve (ec);
440                         if (e == null)
441                                 return null;
442
443                         Constant c = e as Constant;
444                         if (c != null)
445                                 return c;
446
447                         Type constant_type = null;
448                         if (mc is MemberBase) {
449                                 constant_type = ((MemberBase)mc).MemberType;
450                         }
451
452                         Const.Error_ExpressionMustBeConstant (constant_type, loc, mc.GetSignatureForError ());
453                         return null;
454                 }
455
456                 /// <summary>
457                 ///   Resolves an expression for LValue assignment
458                 /// </summary>
459                 ///
460                 /// <remarks>
461                 ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
462                 ///   checking and assertion checking on what we expect from Resolve
463                 /// </remarks>
464                 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
465                 {
466                         int errors = Report.Errors;
467                         bool out_access = right_side == EmptyExpression.OutAccess;
468
469                         Expression e = DoResolveLValue (ec, right_side);
470
471                         if (e != null && out_access && !(e is IMemoryLocation)) {
472                                 // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
473                                 //        Enabling this 'throw' will "only" result in deleting useless code elsewhere,
474
475                                 //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
476                                 //                                e.GetType () + " " + e.GetSignatureForError ());
477                                 e = null;
478                         }
479
480                         if (e == null) {
481                                 if (errors == Report.Errors) {
482                                         if (out_access)
483                                                 Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
484                                         else
485                                                 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
486                                 }
487                                 return null;
488                         }
489
490                         if (e.eclass == ExprClass.Invalid)
491                                 throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
492
493                         if (e.eclass == ExprClass.MethodGroup) {
494                                 ((MethodGroupExpr) e).ReportUsageError ();
495                                 return null;
496                         }
497
498                         if (e.type == null)
499                                 throw new Exception ("Expression " + e + " did not set its type after Resolve");
500
501                         return e;
502                 }
503
504                 /// <summary>
505                 ///   Emits the code for the expression
506                 /// </summary>
507                 ///
508                 /// <remarks>
509                 ///   The Emit method is invoked to generate the code
510                 ///   for the expression.  
511                 /// </remarks>
512                 public abstract void Emit (EmitContext ec);
513
514                 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
515                 {
516                         Emit (ec);
517                         ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
518                 }
519
520                 /// <summary>
521                 ///   Protected constructor.  Only derivate types should
522                 ///   be able to be created
523                 /// </summary>
524
525                 protected Expression ()
526                 {
527                         eclass = ExprClass.Invalid;
528                         type = null;
529                 }
530
531                 /// <summary>
532                 ///   Returns a literalized version of a literal FieldInfo
533                 /// </summary>
534                 ///
535                 /// <remarks>
536                 ///   The possible return values are:
537                 ///      IntConstant, UIntConstant
538                 ///      LongLiteral, ULongConstant
539                 ///      FloatConstant, DoubleConstant
540                 ///      StringConstant
541                 ///
542                 ///   The value returned is already resolved.
543                 /// </remarks>
544                 public static Constant Constantify (object v, Type t)
545                 {
546                         if (t == TypeManager.int32_type)
547                                 return new IntConstant ((int) v, Location.Null);
548                         else if (t == TypeManager.uint32_type)
549                                 return new UIntConstant ((uint) v, Location.Null);
550                         else if (t == TypeManager.int64_type)
551                                 return new LongConstant ((long) v, Location.Null);
552                         else if (t == TypeManager.uint64_type)
553                                 return new ULongConstant ((ulong) v, Location.Null);
554                         else if (t == TypeManager.float_type)
555                                 return new FloatConstant ((float) v, Location.Null);
556                         else if (t == TypeManager.double_type)
557                                 return new DoubleConstant ((double) v, Location.Null);
558                         else if (t == TypeManager.string_type)
559                                 return new StringConstant ((string) v, Location.Null);
560                         else if (t == TypeManager.short_type)
561                                 return new ShortConstant ((short)v, Location.Null);
562                         else if (t == TypeManager.ushort_type)
563                                 return new UShortConstant ((ushort)v, Location.Null);
564                         else if (t == TypeManager.sbyte_type)
565                                 return new SByteConstant ((sbyte)v, Location.Null);
566                         else if (t == TypeManager.byte_type)
567                                 return new ByteConstant ((byte)v, Location.Null);
568                         else if (t == TypeManager.char_type)
569                                 return new CharConstant ((char)v, Location.Null);
570                         else if (t == TypeManager.bool_type)
571                                 return new BoolConstant ((bool) v, Location.Null);
572                         else if (t == TypeManager.decimal_type)
573                                 return new DecimalConstant ((decimal) v, Location.Null);
574                         else if (TypeManager.IsEnumType (t)){
575                                 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
576                                 if (real_type == t)
577                                         real_type = System.Enum.GetUnderlyingType (real_type);
578
579                                 Constant e = Constantify (v, real_type);
580
581                                 return new EnumConstant (e, t);
582                         } else if (v == null && !TypeManager.IsValueType (t))
583                                 return new NullLiteral (Location.Null);
584                         else
585                                 throw new Exception ("Unknown type for constant (" + t +
586                                                      "), details: " + v);
587                 }
588
589                 /// <summary>
590                 ///   Returns a fully formed expression after a MemberLookup
591                 /// </summary>
592                 /// 
593                 public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
594                 {
595                         if (mi is EventInfo)
596                                 return new EventExpr ((EventInfo) mi, loc);
597                         else if (mi is FieldInfo)
598                                 return new FieldExpr ((FieldInfo) mi, loc);
599                         else if (mi is PropertyInfo)
600                                 return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
601                         else if (mi is Type){
602                                 return new TypeExpression ((System.Type) mi, loc);
603                         }
604
605                         return null;
606                 }
607
608                 protected static ArrayList almostMatchedMembers = new ArrayList (4);
609
610                 //
611                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
612                 //
613                 // This code could use some optimizations, but we need to do some
614                 // measurements.  For example, we could use a delegate to `flag' when
615                 // something can not any longer be a method-group (because it is something
616                 // else).
617                 //
618                 // Return values:
619                 //     If the return value is an Array, then it is an array of
620                 //     MethodBases
621                 //   
622                 //     If the return value is an MemberInfo, it is anything, but a Method
623                 //
624                 //     null on error.
625                 //
626                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
627                 // the arguments here and have MemberLookup return only the methods that
628                 // match the argument count/type, unlike we are doing now (we delay this
629                 // decision).
630                 //
631                 // This is so we can catch correctly attempts to invoke instance methods
632                 // from a static body (scan for error 120 in ResolveSimpleName).
633                 //
634                 //
635                 // FIXME: Potential optimization, have a static ArrayList
636                 //
637
638                 public static Expression MemberLookup (Type container_type, Type queried_type, string name,
639                                                        MemberTypes mt, BindingFlags bf, Location loc)
640                 {
641                         return MemberLookup (container_type, null, queried_type, name, mt, bf, loc);
642                 }
643
644                 //
645                 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
646                 // `qualifier_type' or null to lookup members in the current class.
647                 //
648
649                 public static Expression MemberLookup (Type container_type,
650                                                        Type qualifier_type, Type queried_type,
651                                                        string name, MemberTypes mt,
652                                                        BindingFlags bf, Location loc)
653                 {
654                         almostMatchedMembers.Clear ();
655
656                         MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
657                                                                      queried_type, mt, bf, name, almostMatchedMembers);
658
659                         if (mi == null)
660                                 return null;
661
662                         if (mi.Length > 1) {
663                                 bool is_interface = qualifier_type != null && qualifier_type.IsInterface;
664                                 MemberInfo non_method = null;
665                                 ArrayList methods = new ArrayList (2);
666
667                                 foreach (MemberInfo m in mi) {
668                                         if (m is MethodBase) {
669                                                 methods.Add (m);
670                                                 continue;
671                                         }
672
673                                         if (non_method == null) {
674                                                 non_method = m;
675                                                 continue;
676                                         }
677
678                                         if (!is_interface)
679                                                 continue;
680
681                                         Report.SymbolRelatedToPreviousError (m);
682                                         Report.SymbolRelatedToPreviousError (non_method);
683                                         Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
684                                                 TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (non_method));
685                                         return null;
686                                 }
687
688                                 if (non_method != null && is_interface) {
689                                         MethodBase method = (MethodBase)methods[0];
690                                         Report.SymbolRelatedToPreviousError (method);
691                                         Report.SymbolRelatedToPreviousError (non_method);
692                                         Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
693                                                 TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method));
694                                 }
695
696                                 if (methods.Count == 0)
697                                         return new MethodGroupExpr (mi, loc);
698
699                                 return new MethodGroupExpr (methods, loc);
700                         }
701
702                         if (mi [0] is MethodBase)
703                                 return new MethodGroupExpr (mi, loc);
704
705                         return ExprClassFromMemberInfo (container_type, mi [0], loc);
706                 }
707
708                 public const MemberTypes AllMemberTypes =
709                         MemberTypes.Constructor |
710                         MemberTypes.Event       |
711                         MemberTypes.Field       |
712                         MemberTypes.Method      |
713                         MemberTypes.NestedType  |
714                         MemberTypes.Property;
715                 
716                 public const BindingFlags AllBindingFlags =
717                         BindingFlags.Public |
718                         BindingFlags.Static |
719                         BindingFlags.Instance;
720
721                 public static Expression MemberLookup (Type container_type, Type queried_type,
722                                                        string name, Location loc)
723                 {
724                         return MemberLookup (container_type, null, queried_type, name,
725                                              AllMemberTypes, AllBindingFlags, loc);
726                 }
727
728                 public static Expression MemberLookup (Type container_type, Type qualifier_type,
729                                                        Type queried_type, string name, Location loc)
730                 {
731                         return MemberLookup (container_type, qualifier_type, queried_type,
732                                              name, AllMemberTypes, AllBindingFlags, loc);
733                 }
734
735                 public static Expression MethodLookup (EmitContext ec, Type queried_type,
736                                                        string name, Location loc)
737                 {
738                         return MemberLookup (ec.ContainerType, null, queried_type, name,
739                                              MemberTypes.Method, AllBindingFlags, loc);
740                 }
741
742                 /// <summary>
743                 ///   This is a wrapper for MemberLookup that is not used to "probe", but
744                 ///   to find a final definition.  If the final definition is not found, we
745                 ///   look for private members and display a useful debugging message if we
746                 ///   find it.
747                 /// </summary>
748                 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
749                                                             Type queried_type, string name, Location loc)
750                 {
751                         return MemberLookupFinal (ec, qualifier_type, queried_type, name,
752                                                   AllMemberTypes, AllBindingFlags, loc);
753                 }
754
755                 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
756                                                             Type queried_type, string name,
757                                                             MemberTypes mt, BindingFlags bf,
758                                                             Location loc)
759                 {
760                         Expression e;
761
762                         int errors = Report.Errors;
763
764                         e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
765
766                         if (e == null && errors == Report.Errors)
767                                 // No errors were reported by MemberLookup, but there was an error.
768                                 MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
769
770                         return e;
771                 }
772
773                 public static void MemberLookupFailed (Type container_type, Type qualifier_type,
774                                                        Type queried_type, string name,
775                                                        string class_name, bool complain_if_none_found, 
776                                                        Location loc)
777                 {
778                         if (almostMatchedMembers.Count != 0) {
779                                 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
780                                         MemberInfo m = (MemberInfo) almostMatchedMembers [i];
781                                         for (int j = 0; j < i; ++j) {
782                                                 if (m == almostMatchedMembers [j]) {
783                                                         m = null;
784                                                         break;
785                                                 }
786                                         }
787                                         if (m == null)
788                                                 continue;
789                                         
790                                         Type declaring_type = m.DeclaringType;
791                                         
792                                         Report.SymbolRelatedToPreviousError (m);
793                                         if (qualifier_type == null) {
794                                                 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
795                                                               TypeManager.CSharpName (m.DeclaringType),
796                                                               TypeManager.CSharpName (container_type));
797                                                 
798                                         } else if (qualifier_type != container_type &&
799                                                    TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) {
800                                                 // Although a derived class can access protected members of
801                                                 // its base class it cannot do so through an instance of the
802                                                 // base class (CS1540).  If the qualifier_type is a base of the
803                                                 // ec.ContainerType and the lookup succeeds with the latter one,
804                                                 // then we are in this situation.
805                                                 Error_CannotAccessProtected (loc, m, qualifier_type, container_type);
806                                         } else {
807                                                 Report.SymbolRelatedToPreviousError (m);
808                                                 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
809                                         }
810                                 }
811                                 almostMatchedMembers.Clear ();
812                                 return;
813                         }
814
815                         MemberInfo[] lookup = null;
816                         if (queried_type == null) {
817                                 class_name = "global::";
818                         } else {
819                                 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
820                                         AllMemberTypes, AllBindingFlags |
821                                         BindingFlags.NonPublic, name, null);
822                         }
823
824                         if (lookup == null) {
825                                 if (!complain_if_none_found)
826                                         return;
827
828                                 if (class_name != null)
829                                         Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
830                                                 name, class_name);
831                                 else
832                                         Error_TypeDoesNotContainDefinition (loc, queried_type, name);
833                                 return;
834                         }
835
836                         MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
837                                 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
838                         if (name == ".ctor" && ml.Count == 0)
839                         {
840                                 Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
841                                 return;
842                         }
843
844                         Report.SymbolRelatedToPreviousError (lookup [0]);
845                         ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
846                 }
847
848                 /// <summary>
849                 ///   Returns an expression that can be used to invoke operator true
850                 ///   on the expression if it exists.
851                 /// </summary>
852                 static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
853                 {
854                         return GetOperatorTrueOrFalse (ec, e, true, loc);
855                 }
856
857                 /// <summary>
858                 ///   Returns an expression that can be used to invoke operator false
859                 ///   on the expression if it exists.
860                 /// </summary>
861                 static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
862                 {
863                         return GetOperatorTrueOrFalse (ec, e, false, loc);
864                 }
865
866                 static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
867                 {
868                         MethodBase method;
869                         Expression operator_group;
870
871                         operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
872                         if (operator_group == null)
873                                 return null;
874
875                         ArrayList arguments = new ArrayList ();
876                         arguments.Add (new Argument (e, Argument.AType.Expression));
877                         method = Invocation.OverloadResolve (
878                                 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
879
880                         if (method == null)
881                                 return null;
882
883                         return new StaticCallExpr ((MethodInfo) method, arguments, loc);
884                 }
885
886                 /// <summary>
887                 ///   Resolves the expression `e' into a boolean expression: either through
888                 ///   an implicit conversion, or through an `operator true' invocation
889                 /// </summary>
890                 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
891                 {
892                         e = e.Resolve (ec);
893                         if (e == null)
894                                 return null;
895
896                         if (e.Type == TypeManager.bool_type)
897                                 return e;
898
899                         Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
900
901                         if (converted != null)
902                                 return converted;
903
904                         //
905                         // If no implicit conversion to bool exists, try using `operator true'
906                         //
907                         converted = Expression.GetOperatorTrue (ec, e, loc);
908                         if (converted == null){
909                                 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
910                                 return null;
911                         }
912                         return converted;
913                 }
914                 
915                 public virtual string ExprClassName
916                 {
917                         get {
918                                 switch (eclass){
919                                         case ExprClass.Invalid:
920                                                 return "Invalid";
921                                         case ExprClass.Value:
922                                                 return "value";
923                                         case ExprClass.Variable:
924                                                 return "variable";
925                                         case ExprClass.Namespace:
926                                                 return "namespace";
927                                         case ExprClass.Type:
928                                                 return "type";
929                                         case ExprClass.MethodGroup:
930                                                 return "method group";
931                                         case ExprClass.PropertyAccess:
932                                                 return "property access";
933                                         case ExprClass.EventAccess:
934                                                 return "event access";
935                                         case ExprClass.IndexerAccess:
936                                                 return "indexer access";
937                                         case ExprClass.Nothing:
938                                                 return "null";
939                                 }
940                                 throw new Exception ("Should not happen");
941                         }
942                 }
943                 
944                 /// <summary>
945                 ///   Reports that we were expecting `expr' to be of class `expected'
946                 /// </summary>
947                 public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
948                 {
949                         Error_UnexpectedKind (ds, expected, ExprClassName, loc);
950                 }
951
952                 public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
953                 {
954                         string name = GetSignatureForError ();
955                         if (ds != null)
956                                 name = ds.GetSignatureForError () + '.' + name;
957
958                         Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
959                               name, was, expected);
960                 }
961
962                 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
963                 {
964                         string [] valid = new string [4];
965                         int count = 0;
966
967                         if ((flags & ResolveFlags.VariableOrValue) != 0) {
968                                 valid [count++] = "variable";
969                                 valid [count++] = "value";
970                         }
971
972                         if ((flags & ResolveFlags.Type) != 0)
973                                 valid [count++] = "type";
974
975                         if ((flags & ResolveFlags.MethodGroup) != 0)
976                                 valid [count++] = "method group";
977
978                         if (count == 0)
979                                 valid [count++] = "unknown";
980
981                         StringBuilder sb = new StringBuilder (valid [0]);
982                         for (int i = 1; i < count - 1; i++) {
983                                 sb.Append ("', `");
984                                 sb.Append (valid [i]);
985                         }
986                         if (count > 1) {
987                                 sb.Append ("' or `");
988                                 sb.Append (valid [count - 1]);
989                         }
990
991                         Report.Error (119, loc, 
992                                 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
993                 }
994                 
995                 public static void UnsafeError (Location loc)
996                 {
997                         Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
998                 }
999
1000                 //
1001                 // Load the object from the pointer.  
1002                 //
1003                 public static void LoadFromPtr (ILGenerator ig, Type t)
1004                 {
1005                         if (t == TypeManager.int32_type)
1006                                 ig.Emit (OpCodes.Ldind_I4);
1007                         else if (t == TypeManager.uint32_type)
1008                                 ig.Emit (OpCodes.Ldind_U4);
1009                         else if (t == TypeManager.short_type)
1010                                 ig.Emit (OpCodes.Ldind_I2);
1011                         else if (t == TypeManager.ushort_type)
1012                                 ig.Emit (OpCodes.Ldind_U2);
1013                         else if (t == TypeManager.char_type)
1014                                 ig.Emit (OpCodes.Ldind_U2);
1015                         else if (t == TypeManager.byte_type)
1016                                 ig.Emit (OpCodes.Ldind_U1);
1017                         else if (t == TypeManager.sbyte_type)
1018                                 ig.Emit (OpCodes.Ldind_I1);
1019                         else if (t == TypeManager.uint64_type)
1020                                 ig.Emit (OpCodes.Ldind_I8);
1021                         else if (t == TypeManager.int64_type)
1022                                 ig.Emit (OpCodes.Ldind_I8);
1023                         else if (t == TypeManager.float_type)
1024                                 ig.Emit (OpCodes.Ldind_R4);
1025                         else if (t == TypeManager.double_type)
1026                                 ig.Emit (OpCodes.Ldind_R8);
1027                         else if (t == TypeManager.bool_type)
1028                                 ig.Emit (OpCodes.Ldind_I1);
1029                         else if (t == TypeManager.intptr_type)
1030                                 ig.Emit (OpCodes.Ldind_I);
1031                         else if (TypeManager.IsEnumType (t)) {
1032                                 if (t == TypeManager.enum_type)
1033                                         ig.Emit (OpCodes.Ldind_Ref);
1034                                 else
1035                                         LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
1036                         } else if (t.IsValueType)
1037                                 ig.Emit (OpCodes.Ldobj, t);
1038                         else if (t.IsPointer)
1039                                 ig.Emit (OpCodes.Ldind_I);
1040                         else 
1041                                 ig.Emit (OpCodes.Ldind_Ref);
1042                 }
1043
1044                 //
1045                 // The stack contains the pointer and the value of type `type'
1046                 //
1047                 public static void StoreFromPtr (ILGenerator ig, Type type)
1048                 {
1049                         if (TypeManager.IsEnumType (type))
1050                                 type = TypeManager.EnumToUnderlying (type);
1051                         if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
1052                                 ig.Emit (OpCodes.Stind_I4);
1053                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
1054                                 ig.Emit (OpCodes.Stind_I8);
1055                         else if (type == TypeManager.char_type || type == TypeManager.short_type ||
1056                                  type == TypeManager.ushort_type)
1057                                 ig.Emit (OpCodes.Stind_I2);
1058                         else if (type == TypeManager.float_type)
1059                                 ig.Emit (OpCodes.Stind_R4);
1060                         else if (type == TypeManager.double_type)
1061                                 ig.Emit (OpCodes.Stind_R8);
1062                         else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1063                                  type == TypeManager.bool_type)
1064                                 ig.Emit (OpCodes.Stind_I1);
1065                         else if (type == TypeManager.intptr_type)
1066                                 ig.Emit (OpCodes.Stind_I);
1067                         else if (type.IsValueType)
1068                                 ig.Emit (OpCodes.Stobj, type);
1069                         else
1070                                 ig.Emit (OpCodes.Stind_Ref);
1071                 }
1072                 
1073                 //
1074                 // Returns the size of type `t' if known, otherwise, 0
1075                 //
1076                 public static int GetTypeSize (Type t)
1077                 {
1078                         t = TypeManager.TypeToCoreType (t);
1079                         if (t == TypeManager.int32_type ||
1080                             t == TypeManager.uint32_type ||
1081                             t == TypeManager.float_type)
1082                                 return 4;
1083                         else if (t == TypeManager.int64_type ||
1084                                  t == TypeManager.uint64_type ||
1085                                  t == TypeManager.double_type)
1086                                 return 8;
1087                         else if (t == TypeManager.byte_type ||
1088                                  t == TypeManager.sbyte_type ||
1089                                  t == TypeManager.bool_type)    
1090                                 return 1;
1091                         else if (t == TypeManager.short_type ||
1092                                  t == TypeManager.char_type ||
1093                                  t == TypeManager.ushort_type)
1094                                 return 2;
1095                         else if (t == TypeManager.decimal_type)
1096                                 return 16;
1097                         else
1098                                 return 0;
1099                 }
1100
1101                 public static void Error_NegativeArrayIndex (Location loc)
1102                 {
1103                         Report.Error (248, loc, "Cannot create an array with a negative size");
1104                 }
1105
1106                 protected void Error_CannotCallAbstractBase (string name)
1107                 {
1108                         Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1109                 }
1110                 
1111                 //
1112                 // Converts `source' to an int, uint, long or ulong.
1113                 //
1114                 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1115                 {
1116                         Expression target;
1117                         
1118                         using (ec.With (EmitContext.Flags.CheckState, true)) {
1119                                 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1120                                 if (target == null)
1121                                         target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1122                                 if (target == null)
1123                                         target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1124                                 if (target == null)
1125                                         target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1126
1127                                 if (target == null) {
1128                                         source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1129                                         return null;
1130                                 }
1131                         }
1132
1133                         //
1134                         // Only positive constants are allowed at compile time
1135                         //
1136                         if (target is Constant){
1137                                 if (target is IntConstant){
1138                                         if (((IntConstant) target).Value < 0){
1139                                                 Error_NegativeArrayIndex (loc);
1140                                                 return null;
1141                                         }
1142                                 }
1143
1144                                 if (target is LongConstant){
1145                                         if (((LongConstant) target).Value < 0){
1146                                                 Error_NegativeArrayIndex (loc);
1147                                                 return null;
1148                                         }
1149                                 }
1150                                 
1151                         }
1152
1153                         return target;
1154                 }
1155                 
1156         }
1157
1158         /// <summary>
1159         ///   This is just a base class for expressions that can
1160         ///   appear on statements (invocations, object creation,
1161         ///   assignments, post/pre increment and decrement).  The idea
1162         ///   being that they would support an extra Emition interface that
1163         ///   does not leave a result on the stack.
1164         /// </summary>
1165         public abstract class ExpressionStatement : Expression {
1166
1167                 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1168                 {
1169                         Expression e = Resolve (ec);
1170                         if (e == null)
1171                                 return null;
1172
1173                         ExpressionStatement es = e as ExpressionStatement;
1174                         if (es == null)
1175                                 Error (201, "Only assignment, call, increment, decrement and new object " +
1176                                        "expressions can be used as a statement");
1177
1178                         return es;
1179                 }
1180
1181                 /// <summary>
1182                 ///   Requests the expression to be emitted in a `statement'
1183                 ///   context.  This means that no new value is left on the
1184                 ///   stack after invoking this method (constrasted with
1185                 ///   Emit that will always leave a value on the stack).
1186                 /// </summary>
1187                 public abstract void EmitStatement (EmitContext ec);
1188         }
1189
1190         /// <summary>
1191         ///   This kind of cast is used to encapsulate the child
1192         ///   whose type is child.Type into an expression that is
1193         ///   reported to return "return_type".  This is used to encapsulate
1194         ///   expressions which have compatible types, but need to be dealt
1195         ///   at higher levels with.
1196         ///
1197         ///   For example, a "byte" expression could be encapsulated in one
1198         ///   of these as an "unsigned int".  The type for the expression
1199         ///   would be "unsigned int".
1200         ///
1201         /// </summary>
1202         public class EmptyCast : Expression {
1203                 protected readonly Expression child;
1204
1205                 public EmptyCast (Expression child, Type return_type)
1206                 {
1207                         eclass = child.eclass;
1208                         loc = child.Location;
1209                         type = return_type;
1210                         this.child = child;
1211                 }
1212
1213                 public override Expression DoResolve (EmitContext ec)
1214                 {
1215                         // This should never be invoked, we are born in fully
1216                         // initialized state.
1217
1218                         return this;
1219                 }
1220
1221                 public override void Emit (EmitContext ec)
1222                 {
1223                         child.Emit (ec);
1224                 }
1225
1226                 public override bool GetAttributableValue (Type valueType, out object value)
1227                 {
1228                         return child.GetAttributableValue (valueType, out value);
1229                 }
1230
1231         }
1232         /// <summary>
1233         ///     This is a numeric cast to a Decimal
1234         /// </summary>
1235         public class CastToDecimal : EmptyCast {
1236
1237                 MethodInfo conversion_operator;
1238
1239                 public CastToDecimal (Expression child)
1240                         : this (child, false)
1241                 {
1242                 }
1243
1244                 public CastToDecimal (Expression child, bool find_explicit)
1245                         : base (child, TypeManager.decimal_type)
1246                 {
1247                         conversion_operator = GetConversionOperator (find_explicit);
1248
1249                         if (conversion_operator == null)
1250                                 throw new InternalErrorException ("Outer conversion routine is out of sync");
1251                 }
1252
1253                 // Returns the implicit operator that converts from
1254                 // 'child.Type' to System.Decimal.
1255                 MethodInfo GetConversionOperator (bool find_explicit)
1256                 {
1257                         string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1258                         
1259                         MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1260                                 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1261
1262                         foreach (MethodInfo oper in mi) {
1263                                 ParameterData pd = TypeManager.GetParameterData (oper);
1264
1265                                 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1266                                         return oper;
1267                         }
1268
1269                         return null;
1270                 }
1271                 public override void Emit (EmitContext ec)
1272                 {
1273                         ILGenerator ig = ec.ig;
1274                         child.Emit (ec);
1275
1276                         ig.Emit (OpCodes.Call, conversion_operator);
1277                 }
1278         }
1279
1280         /// <summary>
1281         ///     This is an explicit numeric cast from a Decimal
1282         /// </summary>
1283         public class CastFromDecimal : EmptyCast
1284         {
1285                 static IDictionary operators;
1286
1287                 public CastFromDecimal (Expression child, Type return_type)
1288                         : base (child, return_type)
1289                 {
1290                         if (child.Type != TypeManager.decimal_type)
1291                                 throw new InternalErrorException (
1292                                         "The expected type is Decimal, instead it is " + child.Type.FullName);
1293                 }
1294
1295                 // Returns the explicit operator that converts from an
1296                 // express of type System.Decimal to 'type'.
1297                 public Expression Resolve ()
1298                 {
1299                         if (operators == null) {
1300                                  MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1301                                         TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1302                                         BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1303
1304                                 operators = new System.Collections.Specialized.HybridDictionary ();
1305                                 foreach (MethodInfo oper in all_oper) {
1306                                         ParameterData pd = TypeManager.GetParameterData (oper);
1307                                         if (pd.ParameterType (0) == TypeManager.decimal_type)
1308                                                 operators.Add (oper.ReturnType, oper);
1309                                 }
1310                         }
1311
1312                         return operators.Contains (type) ? this : null;
1313                 }
1314
1315                 public override void Emit (EmitContext ec)
1316                 {
1317                         ILGenerator ig = ec.ig;
1318                         child.Emit (ec);
1319
1320                         ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1321                 }
1322         }
1323
1324         //
1325         // We need to special case this since an empty cast of
1326         // a NullLiteral is still a Constant
1327         //
1328         public class NullCast : Constant {
1329                 public Constant child;
1330                                 
1331                 public NullCast (Constant child, Type return_type):
1332                         base (Location.Null)
1333                 {
1334                         eclass = child.eclass;
1335                         type = return_type;
1336                         this.child = child;
1337                 }
1338
1339                 override public string AsString ()
1340                 {
1341                         return "null";
1342                 }
1343
1344                 public override object GetValue ()
1345                 {
1346                         return null;
1347                 }
1348
1349                 public override Expression DoResolve (EmitContext ec)
1350                 {
1351                         // This should never be invoked, we are born in fully
1352                         // initialized state.
1353
1354                         return this;
1355                 }
1356
1357                 public override void Emit (EmitContext ec)
1358                 {
1359                         child.Emit (ec);
1360                 }
1361
1362                 public override Constant Increment ()
1363                 {
1364                         throw new NotSupportedException ();
1365                 }
1366
1367                 public override bool IsDefaultValue {
1368                         get {
1369                                 return true;
1370                         }
1371                 }
1372
1373                 public override bool IsNegative {
1374                         get {
1375                                 return false;
1376                         }
1377                 }
1378
1379                 public override Constant Reduce (bool inCheckedContext, Type target_type)
1380                 {
1381                         if (type == target_type)
1382                                 return child.Reduce (inCheckedContext, target_type);
1383
1384                         return null;
1385                 }
1386
1387         }
1388
1389
1390         /// <summary>
1391         ///  This class is used to wrap literals which belong inside Enums
1392         /// </summary>
1393         public class EnumConstant : Constant {
1394                 public Constant Child;
1395
1396                 public EnumConstant (Constant child, Type enum_type):
1397                         base (child.Location)
1398                 {
1399                         eclass = child.eclass;
1400                         this.Child = child;
1401                         type = enum_type;
1402                 }
1403                 
1404                 public override Expression DoResolve (EmitContext ec)
1405                 {
1406                         // This should never be invoked, we are born in fully
1407                         // initialized state.
1408
1409                         return this;
1410                 }
1411
1412                 public override void Emit (EmitContext ec)
1413                 {
1414                         Child.Emit (ec);
1415                 }
1416
1417                 public override bool GetAttributableValue (Type valueType, out object value)
1418                 {
1419                         value = GetTypedValue ();
1420                         return true;
1421                 }
1422
1423                 public override string GetSignatureForError()
1424                 {
1425                         return TypeManager.CSharpName (Type);
1426                 }
1427
1428                 public override object GetValue ()
1429                 {
1430                         return Child.GetValue ();
1431                 }
1432
1433                 public override object GetTypedValue ()
1434                 {
1435                         // FIXME: runtime is not ready to work with just emited enums
1436                         if (!RootContext.StdLib) {
1437                                 return Child.GetValue ();
1438                         }
1439
1440                         return System.Enum.ToObject (type, Child.GetValue ());
1441                 }
1442                 
1443                 public override string AsString ()
1444                 {
1445                         return Child.AsString ();
1446                 }
1447
1448                 public override DoubleConstant ConvertToDouble ()
1449                 {
1450                         return Child.ConvertToDouble ();
1451                 }
1452
1453                 public override FloatConstant ConvertToFloat ()
1454                 {
1455                         return Child.ConvertToFloat ();
1456                 }
1457
1458                 public override ULongConstant ConvertToULong ()
1459                 {
1460                         return Child.ConvertToULong ();
1461                 }
1462
1463                 public override LongConstant ConvertToLong ()
1464                 {
1465                         return Child.ConvertToLong ();
1466                 }
1467
1468                 public override UIntConstant ConvertToUInt ()
1469                 {
1470                         return Child.ConvertToUInt ();
1471                 }
1472
1473                 public override IntConstant ConvertToInt ()
1474                 {
1475                         return Child.ConvertToInt ();
1476                 }
1477
1478                 public override Constant Increment()
1479                 {
1480                         return new EnumConstant (Child.Increment (), type);
1481                 }
1482
1483                 public override bool IsDefaultValue {
1484                         get {
1485                                 return Child.IsDefaultValue;
1486                         }
1487                 }
1488
1489                 public override bool IsZeroInteger {
1490                         get { return Child.IsZeroInteger; }
1491                 }
1492
1493                 public override bool IsNegative {
1494                         get {
1495                                 return Child.IsNegative;
1496                         }
1497                 }
1498
1499                 public override Constant Reduce(bool inCheckedContext, Type target_type)
1500                 {
1501                         if (Child.Type == target_type)
1502                                 return Child;
1503
1504                         return Child.Reduce (inCheckedContext, target_type);
1505                 }
1506
1507                 public override Constant ToType (Type type, Location loc)
1508                 {
1509                         if (Type == type) {
1510                                 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1511                                 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1512                                         return this;
1513
1514                                 if (type.UnderlyingSystemType != Child.Type)
1515                                         Child = Child.ToType (type.UnderlyingSystemType, loc);
1516                                 return this;
1517                         }
1518
1519                         if (!Convert.ImplicitStandardConversionExists (this, type)){
1520                                 Error_ValueCannotBeConverted (loc, type, false);
1521                                 return null;
1522                         }
1523
1524                         return Child.ToType (type, loc);
1525                 }
1526
1527         }
1528
1529         /// <summary>
1530         ///   This kind of cast is used to encapsulate Value Types in objects.
1531         ///
1532         ///   The effect of it is to box the value type emitted by the previous
1533         ///   operation.
1534         /// </summary>
1535         public class BoxedCast : EmptyCast {
1536
1537                 public BoxedCast (Expression expr, Type target_type)
1538                         : base (expr, target_type)
1539                 {
1540                         eclass = ExprClass.Value;
1541                 }
1542                 
1543                 public override Expression DoResolve (EmitContext ec)
1544                 {
1545                         // This should never be invoked, we are born in fully
1546                         // initialized state.
1547
1548                         return this;
1549                 }
1550
1551                 public override void Emit (EmitContext ec)
1552                 {
1553                         base.Emit (ec);
1554                         
1555                         ec.ig.Emit (OpCodes.Box, child.Type);
1556                 }
1557         }
1558
1559         public class UnboxCast : EmptyCast {
1560                 public UnboxCast (Expression expr, Type return_type)
1561                         : base (expr, return_type)
1562                 {
1563                 }
1564
1565                 public override Expression DoResolve (EmitContext ec)
1566                 {
1567                         // This should never be invoked, we are born in fully
1568                         // initialized state.
1569
1570                         return this;
1571                 }
1572
1573                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1574                 {
1575                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
1576                                 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1577                         return base.DoResolveLValue (ec, right_side);
1578                 }
1579
1580                 public override void Emit (EmitContext ec)
1581                 {
1582                         Type t = type;
1583                         ILGenerator ig = ec.ig;
1584                         
1585                         base.Emit (ec);
1586                         ig.Emit (OpCodes.Unbox, t);
1587
1588                         LoadFromPtr (ig, t);
1589                 }
1590         }
1591         
1592         /// <summary>
1593         ///   This is used to perform explicit numeric conversions.
1594         ///
1595         ///   Explicit numeric conversions might trigger exceptions in a checked
1596         ///   context, so they should generate the conv.ovf opcodes instead of
1597         ///   conv opcodes.
1598         /// </summary>
1599         public class ConvCast : EmptyCast {
1600                 public enum Mode : byte {
1601                         I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1602                         U1_I1, U1_CH,
1603                         I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1604                         U2_I1, U2_U1, U2_I2, U2_CH,
1605                         I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1606                         U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1607                         I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1608                         U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1609                         CH_I1, CH_U1, CH_I2,
1610                         R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1611                         R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1612                 }
1613
1614                 Mode mode;
1615                 
1616                 public ConvCast (Expression child, Type return_type, Mode m)
1617                         : base (child, return_type)
1618                 {
1619                         mode = m;
1620                 }
1621
1622                 public override Expression DoResolve (EmitContext ec)
1623                 {
1624                         // This should never be invoked, we are born in fully
1625                         // initialized state.
1626
1627                         return this;
1628                 }
1629
1630                 public override string ToString ()
1631                 {
1632                         return String.Format ("ConvCast ({0}, {1})", mode, child);
1633                 }
1634                 
1635                 public override void Emit (EmitContext ec)
1636                 {
1637                         ILGenerator ig = ec.ig;
1638                         
1639                         base.Emit (ec);
1640
1641                         if (ec.CheckState){
1642                                 switch (mode){
1643                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1644                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1645                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1646                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1647                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1648
1649                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1650                                 case Mode.U1_CH: /* nothing */ break;
1651
1652                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1653                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1654                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1655                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1656                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1657                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1658
1659                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1660                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1661                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1662                                 case Mode.U2_CH: /* nothing */ break;
1663
1664                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1665                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1666                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1667                                 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1668                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1669                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1670                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1671
1672                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1673                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1674                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1675                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1676                                 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1677                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1678
1679                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1680                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1681                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1682                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1683                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1684                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1685                                 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1686                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1687
1688                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1689                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1690                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1691                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1692                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1693                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1694                                 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1695                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1696
1697                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1698                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1699                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1700
1701                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1702                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1703                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1704                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1705                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1706                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1707                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1708                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1709                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1710
1711                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1712                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1713                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1714                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1715                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1716                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1717                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1718                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1719                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1720                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1721                                 }
1722                         } else {
1723                                 switch (mode){
1724                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1725                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1726                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1727                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1728                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1729
1730                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1731                                 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1732
1733                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1734                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1735                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1736                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1737                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1738                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1739
1740                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1741                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1742                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1743                                 case Mode.U2_CH: /* nothing */ break;
1744
1745                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1746                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1747                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1748                                 case Mode.I4_U4: /* nothing */ break;
1749                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1750                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1751                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1752
1753                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1754                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1755                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1756                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1757                                 case Mode.U4_I4: /* nothing */ break;
1758                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1759
1760                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1761                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1762                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1763                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1764                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1765                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1766                                 case Mode.I8_U8: /* nothing */ break;
1767                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1768
1769                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1770                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1771                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1772                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1773                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1774                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1775                                 case Mode.U8_I8: /* nothing */ break;
1776                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1777
1778                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1779                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1780                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1781
1782                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1783                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1784                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1785                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1786                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1787                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1788                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1789                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1790                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1791
1792                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1793                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1794                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1795                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1796                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1797                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1798                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1799                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1800                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1801                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1802                                 }
1803                         }
1804                 }
1805         }
1806         
1807         public class OpcodeCast : EmptyCast {
1808                 OpCode op, op2;
1809                 bool second_valid;
1810                 
1811                 public OpcodeCast (Expression child, Type return_type, OpCode op)
1812                         : base (child, return_type)
1813                         
1814                 {
1815                         this.op = op;
1816                         second_valid = false;
1817                 }
1818
1819                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1820                         : base (child, return_type)
1821                         
1822                 {
1823                         this.op = op;
1824                         this.op2 = op2;
1825                         second_valid = true;
1826                 }
1827
1828                 public override Expression DoResolve (EmitContext ec)
1829                 {
1830                         // This should never be invoked, we are born in fully
1831                         // initialized state.
1832
1833                         return this;
1834                 }
1835
1836                 public override void Emit (EmitContext ec)
1837                 {
1838                         base.Emit (ec);
1839                         ec.ig.Emit (op);
1840
1841                         if (second_valid)
1842                                 ec.ig.Emit (op2);
1843                 }                       
1844         }
1845
1846         /// <summary>
1847         ///   This kind of cast is used to encapsulate a child and cast it
1848         ///   to the class requested
1849         /// </summary>
1850         public class ClassCast : EmptyCast {
1851                 public ClassCast (Expression child, Type return_type)
1852                         : base (child, return_type)
1853                         
1854                 {
1855                 }
1856
1857                 public override Expression DoResolve (EmitContext ec)
1858                 {
1859                         // This should never be invoked, we are born in fully
1860                         // initialized state.
1861
1862                         return this;
1863                 }
1864
1865                 public override void Emit (EmitContext ec)
1866                 {
1867                         base.Emit (ec);
1868
1869                         ec.ig.Emit (OpCodes.Castclass, type);
1870                 }                       
1871                 
1872         }
1873         
1874         /// <summary>
1875         ///   SimpleName expressions are formed of a single word and only happen at the beginning 
1876         ///   of a dotted-name.
1877         /// </summary>
1878         public class SimpleName : Expression {
1879                 public string Name;
1880                 bool in_transit;
1881
1882                 public SimpleName (string name, Location l)
1883                 {
1884                         Name = name;
1885                         loc = l;
1886                 }
1887
1888                 public static string RemoveGenericArity (string name)
1889                 {
1890                         return name;
1891                 }
1892
1893                 public SimpleName GetMethodGroup ()
1894                 {
1895                         return new SimpleName (RemoveGenericArity (Name), loc);
1896                 }
1897
1898                 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1899                 {
1900                         if (ec.IsFieldInitializer)
1901                                 Report.Error (236, l,
1902                                         "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1903                                         name);
1904                         else
1905                                 Report.Error (
1906                                         120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1907                                         name);
1908                 }
1909
1910                 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1911                 {
1912                         return resolved_to != null && resolved_to.Type != null && 
1913                                 resolved_to.Type.Name == Name &&
1914                                 (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1915                 }
1916
1917                 public override Expression DoResolve (EmitContext ec)
1918                 {
1919                         return SimpleNameResolve (ec, null, false);
1920                 }
1921
1922                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1923                 {
1924                         return SimpleNameResolve (ec, right_side, false);
1925                 }
1926                 
1927
1928                 public Expression DoResolve (EmitContext ec, bool intermediate)
1929                 {
1930                         return SimpleNameResolve (ec, null, intermediate);
1931                 }
1932
1933                 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1934                 {
1935                         int errors = Report.Errors;
1936                         FullNamedExpression fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1937                         if (fne != null)
1938                                 return fne;
1939
1940                         if (silent || errors != Report.Errors)
1941                                 return null;
1942
1943                         MemberCore mc = ec.DeclContainer.GetDefinition (Name);
1944                         if (mc != null) {
1945                                 Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
1946                                 return null;
1947                         }
1948
1949                         string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
1950                         string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
1951                         foreach (Assembly a in RootNamespace.Global.Assemblies) {
1952                                 Type type = a.GetType (fullname);
1953                                 if (type != null) {
1954                                         Report.SymbolRelatedToPreviousError (type);
1955                                         Expression.ErrorIsInaccesible (loc, fullname);
1956                                         return null;
1957                                 }
1958                         }
1959
1960                         NamespaceEntry.Error_NamespaceNotFound (loc, Name);
1961                         return null;
1962                 }
1963
1964                 // TODO: I am still not convinced about this. If someone else will need it
1965                 // implement this as virtual property in MemberCore hierarchy
1966                 string GetMemberType (MemberCore mc)
1967                 {
1968                         if (mc is PropertyBase)
1969                                 return "property";
1970                         if (mc is Indexer)
1971                                 return "indexer";
1972                         if (mc is FieldBase)
1973                                 return "field";
1974                         if (mc is MethodCore)
1975                                 return "method";
1976                         if (mc is EnumMember)
1977                                 return "enum";
1978
1979                         return "type";
1980                 }
1981
1982                 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1983                 {
1984                         if (in_transit)
1985                                 return null;
1986                         in_transit = true;
1987
1988                         Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
1989                         if (e == null)
1990                                 return null;
1991
1992                         if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
1993                                 return e;
1994
1995                         return null;
1996                 }
1997
1998                 /// <remarks>
1999                 ///   7.5.2: Simple Names. 
2000                 ///
2001                 ///   Local Variables and Parameters are handled at
2002                 ///   parse time, so they never occur as SimpleNames.
2003                 ///
2004                 ///   The `intermediate' flag is used by MemberAccess only
2005                 ///   and it is used to inform us that it is ok for us to 
2006                 ///   avoid the static check, because MemberAccess might end
2007                 ///   up resolving the Name as a Type name and the access as
2008                 ///   a static type access.
2009                 ///
2010                 ///   ie: Type Type; .... { Type.GetType (""); }
2011                 ///
2012                 ///   Type is both an instance variable and a Type;  Type.GetType
2013                 ///   is the static method not an instance method of type.
2014                 /// </remarks>
2015                 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2016                 {
2017                         Expression e = null;
2018
2019                         //
2020                         // Stage 1: Performed by the parser (binding to locals or parameters).
2021                         //
2022                         Block current_block = ec.CurrentBlock;
2023                         if (current_block != null){
2024                                 LocalInfo vi = current_block.GetLocalInfo (Name);
2025                                 if (vi != null){
2026                                         LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2027                                         if (right_side != null) {
2028                                                 return var.ResolveLValue (ec, right_side, loc);
2029                                         } else {
2030                                                 ResolveFlags rf = ResolveFlags.VariableOrValue;
2031                                                 if (intermediate)
2032                                                         rf |= ResolveFlags.DisableFlowAnalysis;
2033                                                 return var.Resolve (ec, rf);
2034                                         }
2035                                 }
2036
2037                                 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
2038                                 if (pref != null) {
2039                                         if (right_side != null)
2040                                                 return pref.ResolveLValue (ec, right_side, loc);
2041                                         else
2042                                                 return pref.Resolve (ec);
2043                                 }
2044                         }
2045                         
2046                         //
2047                         // Stage 2: Lookup members 
2048                         //
2049
2050                         DeclSpace lookup_ds = ec.DeclContainer;
2051                         Type almost_matched_type = null;
2052                         ArrayList almost_matched = null;
2053                         do {
2054                                 if (lookup_ds.TypeBuilder == null)
2055                                         break;
2056
2057                                 e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
2058                                 if (e != null)
2059                                         break;
2060
2061                                 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2062                                         almost_matched_type = lookup_ds.TypeBuilder;
2063                                         almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2064                                 }
2065
2066                                 lookup_ds =lookup_ds.Parent;
2067                         } while (lookup_ds != null);
2068                                 
2069                         if (e == null && ec.ContainerType != null)
2070                                 e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
2071
2072                         if (e == null) {
2073                                 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2074                                         almost_matched_type = ec.ContainerType;
2075                                         almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2076                                 }
2077                                 e = ResolveAsTypeStep (ec, true);
2078                         }
2079
2080                         if (e == null) {
2081                                 if (almost_matched != null)
2082                                         almostMatchedMembers = almost_matched;
2083                                 if (almost_matched_type == null)
2084                                         almost_matched_type = ec.ContainerType;
2085                                 MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
2086                                 return null;
2087                         }
2088
2089                         if (e is TypeExpr)
2090                                 return e;
2091
2092                         if (e is MemberExpr) {
2093                                 MemberExpr me = (MemberExpr) e;
2094
2095                                 Expression left;
2096                                 if (me.IsInstance) {
2097                                         if (ec.IsStatic || ec.IsFieldInitializer) {
2098                                                 //
2099                                                 // Note that an MemberExpr can be both IsInstance and IsStatic.
2100                                                 // An unresolved MethodGroupExpr can contain both kinds of methods
2101                                                 // and each predicate is true if the MethodGroupExpr contains
2102                                                 // at least one of that kind of method.
2103                                                 //
2104
2105                                                 if (!me.IsStatic &&
2106                                                     (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2107                                                         Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2108                                                         return EmptyExpression.Null;
2109                                                 }
2110
2111                                                 //
2112                                                 // Pass the buck to MemberAccess and Invocation.
2113                                                 //
2114                                                 left = EmptyExpression.Null;
2115                                         } else {
2116                                                 left = ec.GetThis (loc);
2117                                         }
2118                                 } else {
2119                                         left = new TypeExpression (ec.ContainerType, loc);
2120                                 }
2121
2122                                 e = me.ResolveMemberAccess (ec, left, loc, null);
2123                                 if (e == null)
2124                                         return null;
2125
2126                                 me = e as MemberExpr;
2127                                 if (me == null)
2128                                         return e;
2129
2130                                 if (!me.IsStatic &&
2131                                     TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2132                                     me.InstanceExpression.Type != me.DeclaringType &&
2133                                     !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
2134                                     (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2135                                         Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2136                                                 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2137                                         return null;
2138                                 }
2139
2140                                 return (right_side != null)
2141                                         ? me.DoResolveLValue (ec, right_side)
2142                                         : me.DoResolve (ec);
2143                         }
2144
2145                         return e;
2146                 }
2147                 
2148                 public override void Emit (EmitContext ec)
2149                 {
2150                         //
2151                         // If this is ever reached, then we failed to
2152                         // find the name as a namespace
2153                         //
2154
2155                         Error (103, "The name `" + Name +
2156                                "' does not exist in the class `" +
2157                                ec.DeclContainer.Name + "'");
2158                 }
2159
2160                 public override string ToString ()
2161                 {
2162                         return Name;
2163                 }
2164
2165                 public override string GetSignatureForError ()
2166                 {
2167                         return Name;
2168                 }
2169         }
2170
2171         /// <summary>
2172         ///   Represents a namespace or a type.  The name of the class was inspired by
2173         ///   section 10.8.1 (Fully Qualified Names).
2174         /// </summary>
2175         public abstract class FullNamedExpression : Expression {
2176                 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2177                 {
2178                         return this;
2179                 }
2180
2181                 public abstract string FullName {
2182                         get;
2183                 }
2184         }
2185         
2186         /// <summary>
2187         ///   Expression that evaluates to a type
2188         /// </summary>
2189         public abstract class TypeExpr : FullNamedExpression {
2190                 override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2191                 {
2192                         TypeExpr t = DoResolveAsTypeStep (ec);
2193                         if (t == null)
2194                                 return null;
2195
2196                         eclass = ExprClass.Type;
2197                         return t;
2198                 }
2199
2200                 override public Expression DoResolve (EmitContext ec)
2201                 {
2202                         return ResolveAsTypeTerminal (ec, false);
2203                 }
2204
2205                 override public void Emit (EmitContext ec)
2206                 {
2207                         throw new Exception ("Should never be called");
2208                 }
2209
2210                 public virtual bool CheckAccessLevel (DeclSpace ds)
2211                 {
2212                         return ds.CheckAccessLevel (Type);
2213                 }
2214
2215                 public virtual bool AsAccessible (DeclSpace ds, int flags)
2216                 {
2217                         return ds.AsAccessible (Type, flags);
2218                 }
2219
2220                 public virtual bool IsClass {
2221                         get { return Type.IsClass; }
2222                 }
2223
2224                 public virtual bool IsValueType {
2225                         get { return Type.IsValueType; }
2226                 }
2227
2228                 public virtual bool IsInterface {
2229                         get { return Type.IsInterface; }
2230                 }
2231
2232                 public virtual bool IsSealed {
2233                         get { return Type.IsSealed; }
2234                 }
2235
2236                 public virtual bool CanInheritFrom ()
2237                 {
2238                         if (Type == TypeManager.enum_type ||
2239                             (Type == TypeManager.value_type && RootContext.StdLib) ||
2240                             Type == TypeManager.multicast_delegate_type ||
2241                             Type == TypeManager.delegate_type ||
2242                             Type == TypeManager.array_type)
2243                                 return false;
2244
2245                         return true;
2246                 }
2247
2248                 protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
2249
2250                 public abstract string Name {
2251                         get;
2252                 }
2253
2254                 public override bool Equals (object obj)
2255                 {
2256                         TypeExpr tobj = obj as TypeExpr;
2257                         if (tobj == null)
2258                                 return false;
2259
2260                         return Type == tobj.Type;
2261                 }
2262
2263                 public override int GetHashCode ()
2264                 {
2265                         return Type.GetHashCode ();
2266                 }
2267                 
2268                 public override string ToString ()
2269                 {
2270                         return Name;
2271                 }
2272         }
2273
2274         /// <summary>
2275         ///   Fully resolved Expression that already evaluated to a type
2276         /// </summary>
2277         public class TypeExpression : TypeExpr {
2278                 public TypeExpression (Type t, Location l)
2279                 {
2280                         Type = t;
2281                         eclass = ExprClass.Type;
2282                         loc = l;
2283                 }
2284
2285                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2286                 {
2287                         return this;
2288                 }
2289
2290                 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2291                 {
2292                         return this;
2293                 }
2294
2295                 public override string Name {
2296                         get { return Type.ToString (); }
2297                 }
2298
2299                 public override string FullName {
2300                         get { return Type.FullName; }
2301                 }
2302         }
2303
2304         /// <summary>
2305         ///   Used to create types from a fully qualified name.  These are just used
2306         ///   by the parser to setup the core types.  A TypeLookupExpression is always
2307         ///   classified as a type.
2308         /// </summary>
2309         public sealed class TypeLookupExpression : TypeExpr {
2310                 readonly string name;
2311                 
2312                 public TypeLookupExpression (string name)
2313                 {
2314                         this.name = name;
2315                         eclass = ExprClass.Type;
2316                 }
2317
2318                 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2319                 {
2320                         // It's null for corlib compilation only
2321                         if (type == null)
2322                                 return DoResolveAsTypeStep (ec);
2323
2324                         return this;
2325                 }
2326
2327                 static readonly char [] dot_array = { '.' };
2328                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2329                 {
2330                         // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2331                         string rest = null;
2332                         string lookup_name = name;
2333                         int pos = name.IndexOf ('.');
2334                         if (pos >= 0) {
2335                                 rest = name.Substring (pos + 1);
2336                                 lookup_name = name.Substring (0, pos);
2337                         }
2338
2339                         FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
2340
2341                         if (resolved != null && rest != null) {
2342                                 // Now handle the rest of the the name.
2343                                 string [] elements = rest.Split (dot_array);
2344                                 string element;
2345                                 int count = elements.Length;
2346                                 int i = 0;
2347                                 while (i < count && resolved != null && resolved is Namespace) {
2348                                         Namespace ns = resolved as Namespace;
2349                                         element = elements [i++];
2350                                         lookup_name += "." + element;
2351                                         resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
2352                                 }
2353
2354                                 if (resolved != null && resolved is TypeExpr) {
2355                                         Type t = ((TypeExpr) resolved).Type;
2356                                         while (t != null) {
2357                                                 if (!ec.DeclContainer.CheckAccessLevel (t)) {
2358                                                         resolved = null;
2359                                                         lookup_name = t.FullName;
2360                                                         break;
2361                                                 }
2362                                                 if (i == count) {
2363                                                         type = t;
2364                                                         return this;
2365                                                 }
2366                                                 t = TypeManager.GetNestedType (t, elements [i++]);
2367                                         }
2368                                 }
2369                         }
2370
2371                         if (resolved == null) {
2372                                 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2373                                 return null;
2374                         }
2375
2376                         if (!(resolved is TypeExpr)) {
2377                                 resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
2378                                 return null;
2379                         }
2380
2381                         type = resolved.Type;
2382                         return this;
2383                 }
2384
2385                 public override string Name {
2386                         get { return name; }
2387                 }
2388
2389                 public override string FullName {
2390                         get { return name; }
2391                 }
2392         }
2393
2394         public class TypeAliasExpression : TypeExpr {
2395                 TypeExpr texpr;
2396
2397                 public TypeAliasExpression (TypeExpr texpr, Location l)
2398                 {
2399                         this.texpr = texpr;
2400                         loc = texpr.Location;
2401
2402                         eclass = ExprClass.Type;
2403                 }
2404
2405                 public override string Name {
2406                         get { return texpr.Name; }
2407                 }
2408
2409                 public override string FullName {
2410                         get { return texpr.FullName; }
2411                 }
2412
2413                 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2414                 {
2415                         return texpr;
2416                 }
2417
2418                 public override bool CheckAccessLevel (DeclSpace ds)
2419                 {
2420                         return texpr.CheckAccessLevel (ds);
2421                 }
2422
2423                 public override bool AsAccessible (DeclSpace ds, int flags)
2424                 {
2425                         return texpr.AsAccessible (ds, flags);
2426                 }
2427
2428                 public override bool IsClass {
2429                         get { return texpr.IsClass; }
2430                 }
2431
2432                 public override bool IsValueType {
2433                         get { return texpr.IsValueType; }
2434                 }
2435
2436                 public override bool IsInterface {
2437                         get { return texpr.IsInterface; }
2438                 }
2439
2440                 public override bool IsSealed {
2441                         get { return texpr.IsSealed; }
2442                 }
2443         }
2444
2445         /// <summary>
2446         ///   This class denotes an expression which evaluates to a member
2447         ///   of a struct or a class.
2448         /// </summary>
2449         public abstract class MemberExpr : Expression
2450         {
2451                 /// <summary>
2452                 ///   The name of this member.
2453                 /// </summary>
2454                 public abstract string Name {
2455                         get;
2456                 }
2457
2458                 /// <summary>
2459                 ///   Whether this is an instance member.
2460                 /// </summary>
2461                 public abstract bool IsInstance {
2462                         get;
2463                 }
2464
2465                 /// <summary>
2466                 ///   Whether this is a static member.
2467                 /// </summary>
2468                 public abstract bool IsStatic {
2469                         get;
2470                 }
2471
2472                 /// <summary>
2473                 ///   The type which declares this member.
2474                 /// </summary>
2475                 public abstract Type DeclaringType {
2476                         get;
2477                 }
2478
2479                 /// <summary>
2480                 ///   The instance expression associated with this member, if it's a
2481                 ///   non-static member.
2482                 /// </summary>
2483                 public Expression InstanceExpression;
2484
2485                 public static void error176 (Location loc, string name)
2486                 {
2487                         Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2488                                       "with an instance reference, qualify it with a type name instead", name);
2489                 }
2490
2491                 // TODO: possible optimalization
2492                 // Cache resolved constant result in FieldBuilder <-> expression map
2493                 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2494                                                                SimpleName original)
2495                 {
2496                         //
2497                         // Precondition:
2498                         //   original == null || original.Resolve (...) ==> left
2499                         //
2500
2501                         if (left is TypeExpr) {
2502                                 if (!IsStatic) {
2503                                         SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2504                                         return null;
2505                                 }
2506
2507                                 return this;
2508                         }
2509                                 
2510                         if (!IsInstance) {
2511                                 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2512                                         return this;
2513
2514                                 error176 (loc, GetSignatureForError ());
2515                                 return null;
2516                         }
2517
2518                         InstanceExpression = left;
2519
2520                         return this;
2521                 }
2522
2523                 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2524                 {
2525                         if (IsStatic)
2526                                 return;
2527
2528                         if (InstanceExpression == EmptyExpression.Null) {
2529                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2530                                 return;
2531                         }
2532                                 
2533                         if (InstanceExpression.Type.IsValueType) {
2534                                 if (InstanceExpression is IMemoryLocation) {
2535                                         ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2536                                 } else {
2537                                         LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
2538                                         InstanceExpression.Emit (ec);
2539                                         t.Store (ec);
2540                                         t.AddressOf (ec, AddressOp.Store);
2541                                 }
2542                         } else
2543                                 InstanceExpression.Emit (ec);
2544
2545                         if (prepare_for_load)
2546                                 ec.ig.Emit (OpCodes.Dup);
2547                 }
2548         }
2549
2550         /// <summary>
2551         ///   MethodGroup Expression.
2552         ///  
2553         ///   This is a fully resolved expression that evaluates to a type
2554         /// </summary>
2555         public class MethodGroupExpr : MemberExpr {
2556                 public MethodBase [] Methods;
2557                 bool identical_type_name = false;
2558                 bool is_base;
2559                 
2560                 public MethodGroupExpr (MemberInfo [] mi, Location l)
2561                 {
2562                         Methods = new MethodBase [mi.Length];
2563                         mi.CopyTo (Methods, 0);
2564                         eclass = ExprClass.MethodGroup;
2565                         type = TypeManager.object_type;
2566                         loc = l;
2567                 }
2568
2569                 public MethodGroupExpr (ArrayList list, Location l)
2570                 {
2571                         Methods = new MethodBase [list.Count];
2572
2573                         try {
2574                                 list.CopyTo (Methods, 0);
2575                         } catch {
2576                                 foreach (MemberInfo m in list){
2577                                         if (!(m is MethodBase)){
2578                                                 Console.WriteLine ("Name " + m.Name);
2579                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2580                                         }
2581                                 }
2582                                 throw;
2583                         }
2584
2585                         loc = l;
2586                         eclass = ExprClass.MethodGroup;
2587                         type = TypeManager.object_type;
2588                 }
2589
2590                 public override Type DeclaringType {
2591                         get {
2592                                 //
2593                                 // The methods are arranged in this order:
2594                                 // derived type -> base type
2595                                 //
2596                                 return Methods [0].DeclaringType;
2597                         }
2598                 }
2599
2600                 public bool IdenticalTypeName {
2601                         get {
2602                                 return identical_type_name;
2603                         }
2604
2605                         set {
2606                                 identical_type_name = value;
2607                         }
2608                 }
2609                 
2610                 public bool IsBase {
2611                         get {
2612                                 return is_base;
2613                         }
2614                         set {
2615                                 is_base = value;
2616                         }
2617                 }
2618
2619                 public override string GetSignatureForError ()
2620                 {
2621                         return TypeManager.CSharpSignature (Methods [0]);
2622                 }
2623
2624                 public override string Name {
2625                         get {
2626                                 return Methods [0].Name;
2627                         }
2628                 }
2629
2630                 public override bool IsInstance {
2631                         get {
2632                                 foreach (MethodBase mb in Methods)
2633                                         if (!mb.IsStatic)
2634                                                 return true;
2635
2636                                 return false;
2637                         }
2638                 }
2639
2640                 public override bool IsStatic {
2641                         get {
2642                                 foreach (MethodBase mb in Methods)
2643                                         if (mb.IsStatic)
2644                                                 return true;
2645
2646                                 return false;
2647                         }
2648                 }
2649
2650                 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2651                                                                 SimpleName original)
2652                 {
2653                         if (!(left is TypeExpr) &&
2654                             original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2655                                 IdenticalTypeName = true;
2656
2657                         return base.ResolveMemberAccess (ec, left, loc, original);
2658                 }
2659                 
2660                 override public Expression DoResolve (EmitContext ec)
2661                 {
2662                         if (!IsInstance)
2663                                 InstanceExpression = null;
2664
2665                         if (InstanceExpression != null) {
2666                                 InstanceExpression = InstanceExpression.DoResolve (ec);
2667                                 if (InstanceExpression == null)
2668                                         return null;
2669                         }
2670
2671                         return this;
2672                 }
2673
2674                 public void ReportUsageError ()
2675                 {
2676                         Report.Error (654, loc, "Method `" + DeclaringType + "." +
2677                                       Name + "()' is referenced without parentheses");
2678                 }
2679
2680                 override public void Emit (EmitContext ec)
2681                 {
2682                         ReportUsageError ();
2683                 }
2684
2685                 bool RemoveMethods (bool keep_static)
2686                 {
2687                         ArrayList smethods = new ArrayList ();
2688
2689                         foreach (MethodBase mb in Methods){
2690                                 if (mb.IsStatic == keep_static)
2691                                         smethods.Add (mb);
2692                         }
2693
2694                         if (smethods.Count == 0)
2695                                 return false;
2696
2697                         Methods = new MethodBase [smethods.Count];
2698                         smethods.CopyTo (Methods, 0);
2699
2700                         return true;
2701                 }
2702                 
2703                 /// <summary>
2704                 ///   Removes any instance methods from the MethodGroup, returns
2705                 ///   false if the resulting set is empty.
2706                 /// </summary>
2707                 public bool RemoveInstanceMethods ()
2708                 {
2709                         return RemoveMethods (true);
2710                 }
2711
2712                 /// <summary>
2713                 ///   Removes any static methods from the MethodGroup, returns
2714                 ///   false if the resulting set is empty.
2715                 /// </summary>
2716                 public bool RemoveStaticMethods ()
2717                 {
2718                         return RemoveMethods (false);
2719                 }
2720         }
2721
2722         /// <summary>
2723         ///   Fully resolved expression that evaluates to a Field
2724         /// </summary>
2725         public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2726                 public readonly FieldInfo FieldInfo;
2727                 VariableInfo variable_info;
2728
2729                 LocalTemporary temp;
2730                 bool prepared;
2731                 bool in_initializer;
2732
2733                 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2734                         this (fi, l)
2735                 {
2736                         this.in_initializer = in_initializer;
2737                 }
2738                 
2739                 public FieldExpr (FieldInfo fi, Location l)
2740                 {
2741                         FieldInfo = fi;
2742                         eclass = ExprClass.Variable;
2743                         type = fi.FieldType;
2744                         loc = l;
2745                 }
2746
2747                 public override string Name {
2748                         get {
2749                                 return FieldInfo.Name;
2750                         }
2751                 }
2752
2753                 public override bool IsInstance {
2754                         get {
2755                                 return !FieldInfo.IsStatic;
2756                         }
2757                 }
2758
2759                 public override bool IsStatic {
2760                         get {
2761                                 return FieldInfo.IsStatic;
2762                         }
2763                 }
2764
2765                 public override Type DeclaringType {
2766                         get {
2767                                 return FieldInfo.DeclaringType;
2768                         }
2769                 }
2770
2771                 public override string GetSignatureForError ()
2772                 {
2773                         return TypeManager.GetFullNameSignature (FieldInfo);
2774                 }
2775
2776                 public VariableInfo VariableInfo {
2777                         get {
2778                                 return variable_info;
2779                         }
2780                 }
2781
2782                 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2783                                                                 SimpleName original)
2784                 {
2785                         Type t = FieldInfo.FieldType;
2786
2787                         if (FieldInfo.IsLiteral || (FieldInfo.IsInitOnly && t == TypeManager.decimal_type)) {
2788                                 IConstant ic = TypeManager.GetConstant (FieldInfo);
2789                                 if (ic == null) {
2790                                         if (FieldInfo.IsLiteral) {
2791                                                 ic = new ExternalConstant (FieldInfo);
2792                                         } else {
2793                                                 ic = ExternalConstant.CreateDecimal (FieldInfo);
2794                                                 if (ic == null) {
2795                                                         return base.ResolveMemberAccess (ec, left, loc, original);
2796                                                 }
2797                                         }
2798                                         TypeManager.RegisterConstant (FieldInfo, ic);
2799                                 }
2800
2801                                 bool left_is_type = left is TypeExpr;
2802                                 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
2803                                         Report.SymbolRelatedToPreviousError (FieldInfo);
2804                                         error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
2805                                         return null;
2806                                 }
2807
2808                                 if (ic.ResolveValue ()) {
2809                                         if (!ec.IsInObsoleteScope)
2810                                                 ic.CheckObsoleteness (loc);
2811                                 }
2812
2813                                 return ic.Value;
2814                         }
2815                         
2816                         if (t.IsPointer && !ec.InUnsafe) {
2817                                 UnsafeError (loc);
2818                                 return null;
2819                         }
2820
2821                         return base.ResolveMemberAccess (ec, left, loc, original);
2822                 }
2823
2824                 override public Expression DoResolve (EmitContext ec)
2825                 {
2826                         return DoResolve (ec, false, false);
2827                 }
2828
2829                 Expression DoResolve (EmitContext ec, bool lvalue_instance, bool out_access)
2830                 {
2831                         if (!FieldInfo.IsStatic){
2832                                 if (InstanceExpression == null){
2833                                         //
2834                                         // This can happen when referencing an instance field using
2835                                         // a fully qualified type expression: TypeName.InstanceField = xxx
2836                                         // 
2837                                         SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2838                                         return null;
2839                                 }
2840
2841                                 // Resolve the field's instance expression while flow analysis is turned
2842                                 // off: when accessing a field "a.b", we must check whether the field
2843                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2844
2845                                 if (lvalue_instance) {
2846                                         using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) {
2847                                                 Expression right_side =
2848                                                         out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
2849                                                 InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc);
2850                                         }
2851                                 } else {
2852                                         ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
2853                                         InstanceExpression = InstanceExpression.Resolve (ec, rf);
2854                                 }
2855
2856                                 if (InstanceExpression == null)
2857                                         return null;
2858
2859                                 InstanceExpression.CheckMarshalByRefAccess ();
2860                         }
2861
2862                         if (!in_initializer && !ec.IsFieldInitializer) {
2863                                 ObsoleteAttribute oa;
2864                                 FieldBase f = TypeManager.GetField (FieldInfo);
2865                                 if (f != null) {
2866                                         if (!ec.IsInObsoleteScope)
2867                                                 f.CheckObsoleteness (loc);
2868                                 
2869                                         // To be sure that type is external because we do not register generated fields
2870                                 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {                                
2871                                         oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
2872                                         if (oa != null)
2873                                                 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
2874                                 }
2875                         }
2876
2877                         AnonymousContainer am = ec.CurrentAnonymousMethod;
2878                         if (am != null){
2879                                 if (!FieldInfo.IsStatic){
2880                                         if (!am.IsIterator && (ec.TypeContainer is Struct)){
2881                                                 Report.Error (1673, loc,
2882                                                 "Anonymous methods inside structs cannot access instance members of `{0}'. Consider copying `{0}' to a local variable outside the anonymous method and using the local instead",
2883                                                         "this");
2884                                                 return null;
2885                                         }
2886                                         if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
2887                                                 ec.CaptureField (this);
2888                                 }
2889                         }
2890                         
2891                         // If the instance expression is a local variable or parameter.
2892                         IVariable var = InstanceExpression as IVariable;
2893                         if ((var == null) || (var.VariableInfo == null))
2894                                 return this;
2895
2896                         VariableInfo vi = var.VariableInfo;
2897                         if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
2898                                 return null;
2899
2900                         variable_info = vi.GetSubStruct (FieldInfo.Name);
2901                         return this;
2902                 }
2903
2904                 static readonly int [] codes = {
2905                         191,    // instance, write access
2906                         192,    // instance, out access
2907                         198,    // static, write access
2908                         199,    // static, out access
2909                         1648,   // member of value instance, write access
2910                         1649,   // member of value instance, out access
2911                         1650,   // member of value static, write access
2912                         1651    // member of value static, out access
2913                 };
2914
2915                 static readonly string [] msgs = {
2916                         /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
2917                         /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2918                         /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
2919                         /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2920                         /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
2921                         /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2922                         /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
2923                         /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
2924                 };
2925
2926                 // The return value is always null.  Returning a value simplifies calling code.
2927                 Expression Report_AssignToReadonly (Expression right_side)
2928                 {
2929                         int i = 0;
2930                         if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess)
2931                                 i += 1;
2932                         if (IsStatic)
2933                                 i += 2;
2934                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
2935                                 i += 4;
2936                         Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
2937
2938                         return null;
2939                 }
2940                 
2941                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2942                 {
2943                         IVariable var = InstanceExpression as IVariable;
2944                         if ((var != null) && (var.VariableInfo != null))
2945                                 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
2946
2947                         bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
2948                         bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess;
2949
2950                         Expression e = DoResolve (ec, lvalue_instance, out_access);
2951
2952                         if (e == null)
2953                                 return null;
2954
2955                         FieldBase fb = TypeManager.GetField (FieldInfo);
2956                         if (fb != null)
2957                                 fb.SetAssigned ();
2958
2959                         if (FieldInfo.IsInitOnly) {
2960                                 // InitOnly fields can only be assigned in constructors or initializers
2961                                 if (!ec.IsFieldInitializer && !ec.IsConstructor)
2962                                         return Report_AssignToReadonly (right_side);
2963
2964                                 if (ec.IsConstructor) {
2965                                         // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
2966                                         if (ec.ContainerType != FieldInfo.DeclaringType)
2967                                                 return Report_AssignToReadonly (right_side);
2968                                         // static InitOnly fields cannot be assigned-to in an instance constructor
2969                                         if (IsStatic && !ec.IsStatic)
2970                                                 return Report_AssignToReadonly (right_side);
2971                                         // instance constructors can't modify InitOnly fields of other instances of the same type
2972                                         if (!IsStatic && !(InstanceExpression is This))
2973                                                 return Report_AssignToReadonly (right_side);
2974                                 }
2975                         }
2976
2977                         if (right_side == EmptyExpression.OutAccess &&
2978                             !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
2979                                 Report.SymbolRelatedToPreviousError (DeclaringType);
2980                                 Report.Warning (197, 1, loc,
2981                                                 "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
2982                                                 GetSignatureForError ());
2983                         }
2984
2985                         return this;
2986                 }
2987
2988                 public override void CheckMarshalByRefAccess ()
2989                 {
2990                         if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
2991                                 Report.SymbolRelatedToPreviousError (DeclaringType);
2992                                 Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
2993                                                 GetSignatureForError ());
2994                         }
2995                 }
2996
2997                 public bool VerifyFixed ()
2998                 {
2999                         IVariable variable = InstanceExpression as IVariable;
3000                         // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
3001                         // We defer the InstanceExpression check after the variable check to avoid a 
3002                         // separate null check on InstanceExpression.
3003                         return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
3004                 }
3005
3006                 public override int GetHashCode ()
3007                 {
3008                         return FieldInfo.GetHashCode ();
3009                 }
3010
3011                 public override bool Equals (object obj)
3012                 {
3013                         FieldExpr fe = obj as FieldExpr;
3014                         if (fe == null)
3015                                 return false;
3016
3017                         if (FieldInfo != fe.FieldInfo)
3018                                 return false;
3019
3020                         if (InstanceExpression == null || fe.InstanceExpression == null)
3021                                 return true;
3022
3023                         return InstanceExpression.Equals (fe.InstanceExpression);
3024                 }
3025                 
3026                 public void Emit (EmitContext ec, bool leave_copy)
3027                 {
3028                         ILGenerator ig = ec.ig;
3029                         bool is_volatile = false;
3030
3031                         FieldBase f = TypeManager.GetField (FieldInfo);
3032                         if (f != null){
3033                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3034                                         is_volatile = true;
3035
3036                                 f.SetMemberIsUsed ();
3037                         }
3038                         
3039                         if (FieldInfo.IsStatic){
3040                                 if (is_volatile)
3041                                         ig.Emit (OpCodes.Volatile);
3042                                 
3043                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
3044                         } else {
3045                                 if (!prepared)
3046                                         EmitInstance (ec, false);
3047                                 
3048                                 if (is_volatile)
3049                                         ig.Emit (OpCodes.Volatile);
3050
3051                                 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
3052                                 if (ff != null)
3053                                 {
3054                                         ig.Emit (OpCodes.Ldflda, FieldInfo);
3055                                         ig.Emit (OpCodes.Ldflda, ff.Element);
3056                                 }
3057                                 else {
3058                                         ig.Emit (OpCodes.Ldfld, FieldInfo);
3059                                 }
3060                         }
3061
3062                         if (leave_copy) {       
3063                                 ec.ig.Emit (OpCodes.Dup);
3064                                 if (!FieldInfo.IsStatic) {
3065                                         temp = new LocalTemporary (this.Type);
3066                                         temp.Store (ec);
3067                                 }
3068                         }
3069                 }
3070                 
3071                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3072                 {
3073                         FieldAttributes fa = FieldInfo.Attributes;
3074                         bool is_static = (fa & FieldAttributes.Static) != 0;
3075                         bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3076                         ILGenerator ig = ec.ig;
3077                         prepared = prepare_for_load;
3078
3079                         if (is_readonly && !ec.IsConstructor){
3080                                 Report_AssignToReadonly (source);
3081                                 return;
3082                         }
3083
3084                         EmitInstance (ec, prepare_for_load);
3085
3086                         source.Emit (ec);
3087                         if (leave_copy) {
3088                                 ec.ig.Emit (OpCodes.Dup);
3089                                 if (!FieldInfo.IsStatic) {
3090                                         temp = new LocalTemporary (this.Type);
3091                                         temp.Store (ec);
3092                                 }
3093                         }
3094
3095                         if (FieldInfo is FieldBuilder){
3096                                 FieldBase f = TypeManager.GetField (FieldInfo);
3097                                 if (f != null){
3098                                         if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3099                                                 ig.Emit (OpCodes.Volatile);
3100                                         
3101                                         f.SetAssigned ();
3102                                 }
3103                         } 
3104
3105                         if (is_static)
3106                                 ig.Emit (OpCodes.Stsfld, FieldInfo);
3107                         else 
3108                                 ig.Emit (OpCodes.Stfld, FieldInfo);
3109                         
3110                         if (temp != null) {
3111                                 temp.Emit (ec);
3112                                 temp.Release (ec);
3113                         }
3114                 }
3115
3116                 public override void Emit (EmitContext ec)
3117                 {
3118                         Emit (ec, false);
3119                 }
3120
3121                 public void AddressOf (EmitContext ec, AddressOp mode)
3122                 {
3123                         ILGenerator ig = ec.ig;
3124                         
3125                         if (FieldInfo is FieldBuilder){
3126                                 FieldBase f = TypeManager.GetField (FieldInfo);
3127                                 if (f != null){
3128                                         if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3129                                                 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3130                                                         f.GetSignatureForError ());
3131                                                 return;
3132                                         }
3133                                         
3134                                         if ((mode & AddressOp.Store) != 0)
3135                                                 f.SetAssigned ();
3136                                         if ((mode & AddressOp.Load) != 0)
3137                                                 f.SetMemberIsUsed ();
3138                                 }
3139                         } 
3140
3141                         //
3142                         // Handle initonly fields specially: make a copy and then
3143                         // get the address of the copy.
3144                         //
3145                         bool need_copy;
3146                         if (FieldInfo.IsInitOnly){
3147                                 need_copy = true;
3148                                 if (ec.IsConstructor){
3149                                         if (FieldInfo.IsStatic){
3150                                                 if (ec.IsStatic)
3151                                                         need_copy = false;
3152                                         } else
3153                                                 need_copy = false;
3154                                 }
3155                         } else
3156                                 need_copy = false;
3157                         
3158                         if (need_copy){
3159                                 LocalBuilder local;
3160                                 Emit (ec);
3161                                 local = ig.DeclareLocal (type);
3162                                 ig.Emit (OpCodes.Stloc, local);
3163                                 ig.Emit (OpCodes.Ldloca, local);
3164                                 return;
3165                         }
3166
3167
3168                         if (FieldInfo.IsStatic){
3169                                 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3170                         } else {
3171                                 EmitInstance (ec, false);
3172                                 ig.Emit (OpCodes.Ldflda, FieldInfo);
3173                         }
3174                 }
3175         }
3176
3177         //
3178         // A FieldExpr whose address can not be taken
3179         //
3180         public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3181                 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3182                 {
3183                 }
3184                 
3185                 public new void AddressOf (EmitContext ec, AddressOp mode)
3186                 {
3187                         Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3188                 }
3189         }
3190         
3191         /// <summary>
3192         ///   Expression that evaluates to a Property.  The Assign class
3193         ///   might set the `Value' expression if we are in an assignment.
3194         ///
3195         ///   This is not an LValue because we need to re-write the expression, we
3196         ///   can not take data from the stack and store it.  
3197         /// </summary>
3198         public class PropertyExpr : MemberExpr, IAssignMethod {
3199                 public readonly PropertyInfo PropertyInfo;
3200
3201                 //
3202                 // This is set externally by the  `BaseAccess' class
3203                 //
3204                 public bool IsBase;
3205                 MethodInfo getter, setter;
3206                 bool is_static;
3207
3208                 bool resolved;
3209                 
3210                 LocalTemporary temp;
3211                 bool prepared;
3212
3213                 internal static PtrHashtable AccessorTable = new PtrHashtable (); 
3214
3215                 public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
3216                 {
3217                         PropertyInfo = pi;
3218                         eclass = ExprClass.PropertyAccess;
3219                         is_static = false;
3220                         loc = l;
3221
3222                         type = TypeManager.TypeToCoreType (pi.PropertyType);
3223
3224                         ResolveAccessors (containerType);
3225                 }
3226
3227                 public override string Name {
3228                         get {
3229                                 return PropertyInfo.Name;
3230                         }
3231                 }
3232
3233                 public override bool IsInstance {
3234                         get {
3235                                 return !is_static;
3236                         }
3237                 }
3238
3239                 public override bool IsStatic {
3240                         get {
3241                                 return is_static;
3242                         }
3243                 }
3244                 
3245                 public override Type DeclaringType {
3246                         get {
3247                                 return PropertyInfo.DeclaringType;
3248                         }
3249                 }
3250
3251                 public override string GetSignatureForError ()
3252                 {
3253                         return TypeManager.GetFullNameSignature (PropertyInfo);
3254                 }
3255
3256                 void FindAccessors (Type invocation_type)
3257                 {
3258                         const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3259                                 BindingFlags.Static | BindingFlags.Instance |
3260                                 BindingFlags.DeclaredOnly;
3261
3262                         Type current = PropertyInfo.DeclaringType;
3263                         for (; current != null; current = current.BaseType) {
3264                                 MemberInfo[] group = TypeManager.MemberLookup (
3265                                         invocation_type, invocation_type, current,
3266                                         MemberTypes.Property, flags, PropertyInfo.Name, null);
3267
3268                                 if (group == null)
3269                                         continue;
3270
3271                                 if (group.Length != 1)
3272                                         // Oooops, can this ever happen ?
3273                                         return;
3274
3275                                 PropertyInfo pi = (PropertyInfo) group [0];
3276
3277                                 if (getter == null)
3278                                         getter = pi.GetGetMethod (true);
3279
3280                                 if (setter == null)
3281                                         setter = pi.GetSetMethod (true);
3282
3283                                 MethodInfo accessor = getter != null ? getter : setter;
3284
3285                                 if (!accessor.IsVirtual)
3286                                         return;
3287                         }
3288                 }
3289
3290                 //
3291                 // We also perform the permission checking here, as the PropertyInfo does not
3292                 // hold the information for the accessibility of its setter/getter
3293                 //
3294                 // TODO: can use TypeManager.GetProperty to boost performance
3295                 void ResolveAccessors (Type containerType)
3296                 {
3297                         FindAccessors (containerType);
3298
3299                         if (getter != null) {
3300                                 IMethodData md = TypeManager.GetMethod (getter);
3301                                 if (md != null)
3302                                         md.SetMemberIsUsed ();
3303
3304                                 AccessorTable [getter] = PropertyInfo;
3305                                 is_static = getter.IsStatic;
3306                         }
3307
3308                         if (setter != null) {
3309                                 IMethodData md = TypeManager.GetMethod (setter);
3310                                 if (md != null)
3311                                         md.SetMemberIsUsed ();
3312
3313                                 AccessorTable [setter] = PropertyInfo;
3314                                 is_static = setter.IsStatic;
3315                         }
3316                 }
3317
3318                 bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
3319                 {
3320                         if (is_static) {
3321                                 InstanceExpression = null;
3322                                 return true;
3323                         }
3324
3325                         if (InstanceExpression == null) {
3326                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
3327                                 return false;
3328                         }
3329
3330                         if (lvalue_instance)
3331                                 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3332                         else
3333                                 InstanceExpression = InstanceExpression.DoResolve (ec);
3334                         if (InstanceExpression == null)
3335                                 return false;
3336
3337                         InstanceExpression.CheckMarshalByRefAccess ();
3338
3339                         if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3340                             InstanceExpression.Type != ec.ContainerType &&
3341                             ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3342                             !InstanceExpression.Type.IsSubclassOf (ec.ContainerType)) {
3343                                 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3344                                 return false;
3345                         }
3346
3347                         return true;
3348                 }
3349
3350                 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3351                 {
3352                         // TODO: correctly we should compare arguments but it will lead to bigger changes
3353                         if (mi is MethodBuilder) {
3354                                 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3355                                 return;
3356                         }
3357
3358                         StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3359                         sig.Append ('.');
3360                         ParameterData iparams = TypeManager.GetParameterData (mi);
3361                         sig.Append (getter ? "get_" : "set_");
3362                         sig.Append (Name);
3363                         sig.Append (iparams.GetSignatureForError ());
3364
3365                         Report.SymbolRelatedToPreviousError (mi);
3366                         Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3367                                 Name, sig.ToString ());
3368                 }
3369                 
3370                 override public Expression DoResolve (EmitContext ec)
3371                 {
3372                         if (resolved)
3373                                 return this;
3374
3375                         if (getter != null){
3376                                 if (TypeManager.GetParameterData (getter).Count != 0){
3377                                         Error_PropertyNotFound (getter, true);
3378                                         return null;
3379                                 }
3380                         }
3381
3382                         if (getter == null){
3383                                 //
3384                                 // The following condition happens if the PropertyExpr was
3385                                 // created, but is invalid (ie, the property is inaccessible),
3386                                 // and we did not want to embed the knowledge about this in
3387                                 // the caller routine.  This only avoids double error reporting.
3388                                 //
3389                                 if (setter == null)
3390                                         return null;
3391
3392                                 if (InstanceExpression != EmptyExpression.Null) {
3393                                         Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3394                                                 TypeManager.GetFullNameSignature (PropertyInfo));
3395                                         return null;
3396                                 }
3397                         } 
3398
3399                         bool must_do_cs1540_check = false;
3400                         if (getter != null &&
3401                             !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3402                                 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3403                                 if (pm != null && pm.HasCustomAccessModifier) {
3404                                         Report.SymbolRelatedToPreviousError (pm);
3405                                         Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3406                                                 TypeManager.CSharpSignature (getter));
3407                                 }
3408                                 else {
3409                                         Report.SymbolRelatedToPreviousError (getter);
3410                                         ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3411                                 }
3412                                 return null;
3413                         }
3414                         
3415                         if (!InstanceResolve (ec, false, must_do_cs1540_check))
3416                                 return null;
3417
3418                         //
3419                         // Only base will allow this invocation to happen.
3420                         //
3421                         if (IsBase && getter.IsAbstract) {
3422                                 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3423                                 return null;
3424                         }
3425
3426                         if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3427                                 UnsafeError (loc);
3428                                 return null;
3429                         }
3430
3431                         resolved = true;
3432
3433                         return this;
3434                 }
3435
3436                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3437                 {
3438                         if (right_side == EmptyExpression.OutAccess) {
3439                                 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
3440                                               GetSignatureForError ());
3441                                 return null;
3442                         }
3443
3444                         if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
3445                                 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
3446                                               GetSignatureForError ());
3447                                 return null;
3448                         }
3449
3450                         if (setter == null){
3451                                 //
3452                                 // The following condition happens if the PropertyExpr was
3453                                 // created, but is invalid (ie, the property is inaccessible),
3454                                 // and we did not want to embed the knowledge about this in
3455                                 // the caller routine.  This only avoids double error reporting.
3456                                 //
3457                                 if (getter == null)
3458                                         return null;
3459                                 Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
3460                                               GetSignatureForError ());
3461                                 return null;
3462                         }
3463
3464                         if (TypeManager.GetParameterData (setter).Count != 1){
3465                                 Error_PropertyNotFound (setter, false);
3466                                 return null;
3467                         }
3468
3469                         bool must_do_cs1540_check;
3470                         if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3471                                 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3472                                 if (pm != null && pm.HasCustomAccessModifier) {
3473                                         Report.SymbolRelatedToPreviousError (pm);
3474                                         Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3475                                                 TypeManager.CSharpSignature (setter));
3476                                 }
3477                                 else {
3478                                         Report.SymbolRelatedToPreviousError (setter);
3479                                         ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3480                                 }
3481                                 return null;
3482                         }
3483                         
3484                         if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
3485                                 return null;
3486                         
3487                         //
3488                         // Only base will allow this invocation to happen.
3489                         //
3490                         if (IsBase && setter.IsAbstract){
3491                                 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3492                                 return null;
3493                         }
3494
3495                         return this;
3496                 }
3497                 
3498                 public override void Emit (EmitContext ec)
3499                 {
3500                         Emit (ec, false);
3501                 }
3502                 
3503                 public void Emit (EmitContext ec, bool leave_copy)
3504                 {
3505                         //
3506                         // Special case: length of single dimension array property is turned into ldlen
3507                         //
3508                         if ((getter == TypeManager.system_int_array_get_length) ||
3509                             (getter == TypeManager.int_array_get_length)){
3510                                 Type iet = InstanceExpression.Type;
3511
3512                                 //
3513                                 // System.Array.Length can be called, but the Type does not
3514                                 // support invoking GetArrayRank, so test for that case first
3515                                 //
3516                                 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3517                                         if (!prepared)
3518                                                 EmitInstance (ec, false);
3519                                         ec.ig.Emit (OpCodes.Ldlen);
3520                                         ec.ig.Emit (OpCodes.Conv_I4);
3521                                         return;
3522                                 }
3523                         }
3524
3525                         Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3526                         
3527                         if (leave_copy) {
3528                                 ec.ig.Emit (OpCodes.Dup);
3529                                 if (!is_static) {
3530                                         temp = new LocalTemporary (this.Type);
3531                                         temp.Store (ec);
3532                                 }
3533                         }
3534                 }
3535
3536                 //
3537                 // Implements the IAssignMethod interface for assignments
3538                 //
3539                 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3540                 {
3541                         Expression my_source = source;
3542
3543                         prepared = prepare_for_load;
3544                         
3545                         if (prepared) {
3546                                 source.Emit (ec);
3547                                 if (leave_copy) {
3548                                         ec.ig.Emit (OpCodes.Dup);
3549                                         if (!is_static) {
3550                                                 temp = new LocalTemporary (this.Type);
3551                                                 temp.Store (ec);
3552                                         }
3553                                 }
3554                         } else if (leave_copy) {
3555                                 source.Emit (ec);
3556                                 if (!is_static) {
3557                                         temp = new LocalTemporary (this.Type);
3558                                         temp.Store (ec);
3559                                 }
3560                                 my_source = temp;
3561                         }
3562                         
3563                         ArrayList args = new ArrayList (1);
3564                         args.Add (new Argument (my_source, Argument.AType.Expression));
3565                         
3566                         Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3567                         
3568                         if (temp != null) {
3569                                 temp.Emit (ec);
3570                                 temp.Release (ec);
3571                         }
3572                 }
3573         }
3574
3575         /// <summary>
3576         ///   Fully resolved expression that evaluates to an Event
3577         /// </summary>
3578         public class EventExpr : MemberExpr {
3579                 public readonly EventInfo EventInfo;
3580
3581                 bool is_static;
3582                 MethodInfo add_accessor, remove_accessor;
3583
3584                 internal static PtrHashtable AccessorTable = new PtrHashtable (); 
3585                 
3586                 public EventExpr (EventInfo ei, Location loc)
3587                 {
3588                         EventInfo = ei;
3589                         this.loc = loc;
3590                         eclass = ExprClass.EventAccess;
3591
3592                         add_accessor = TypeManager.GetAddMethod (ei);
3593                         remove_accessor = TypeManager.GetRemoveMethod (ei);
3594                         if (add_accessor != null)
3595                                 AccessorTable [add_accessor] = ei;
3596                         if (remove_accessor != null)
3597                                 AccessorTable [remove_accessor] = ei;
3598                         
3599                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
3600                                 is_static = true;
3601
3602                         if (EventInfo is MyEventBuilder){
3603                                 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3604                                 type = eb.EventType;
3605                                 eb.SetUsed ();
3606                         } else
3607                                 type = EventInfo.EventHandlerType;
3608                 }
3609
3610                 public override string Name {
3611                         get {
3612                                 return EventInfo.Name;
3613                         }
3614                 }
3615
3616                 public override bool IsInstance {
3617                         get {
3618                                 return !is_static;
3619                         }
3620                 }
3621
3622                 public override bool IsStatic {
3623                         get {
3624                                 return is_static;
3625                         }
3626                 }
3627
3628                 public override Type DeclaringType {
3629                         get {
3630                                 return EventInfo.DeclaringType;
3631                         }
3632                 }
3633
3634                 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3635                                                                 SimpleName original)
3636                 {
3637                         //
3638                         // If the event is local to this class, we transform ourselves into a FieldExpr
3639                         //
3640
3641                         if (EventInfo.DeclaringType == ec.ContainerType ||
3642                             TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3643                                 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3644
3645                                 if (mi != null) {
3646                                         MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
3647
3648                                         if (ml == null) {
3649                                                 Report.Error (-200, loc, "Internal error!!");
3650                                                 return null;
3651                                         }
3652
3653                                         InstanceExpression = null;
3654                                 
3655                                         return ml.ResolveMemberAccess (ec, left, loc, original);
3656                                 }
3657                         }
3658
3659                         return base.ResolveMemberAccess (ec, left, loc, original);
3660                 }
3661
3662
3663                 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3664                 {
3665                         if (is_static) {
3666                                 InstanceExpression = null;
3667                                 return true;
3668                         }
3669
3670                         if (InstanceExpression == null) {
3671                                 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
3672                                 return false;
3673                         }
3674
3675                         InstanceExpression = InstanceExpression.DoResolve (ec);
3676                         if (InstanceExpression == null)
3677                                 return false;
3678
3679                         //
3680                         // This is using the same mechanism as the CS1540 check in PropertyExpr.
3681                         // However, in the Event case, we reported a CS0122 instead.
3682                         //
3683                         if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3684                             InstanceExpression.Type != ec.ContainerType &&
3685                             ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3686                                 Report.SymbolRelatedToPreviousError (EventInfo);
3687                                 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3688                                 return false;
3689                         }
3690
3691                         return true;
3692                 }
3693
3694                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3695                 {
3696                         return DoResolve (ec);
3697                 }
3698
3699                 public override Expression DoResolve (EmitContext ec)
3700                 {
3701                         bool must_do_cs1540_check;
3702                         if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3703                               IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3704                                 Report.SymbolRelatedToPreviousError (EventInfo);
3705                                 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3706                                 return null;
3707                         }
3708
3709                         if (!InstanceResolve (ec, must_do_cs1540_check))
3710                                 return null;
3711                         
3712                         return this;
3713                 }               
3714
3715                 public override void Emit (EmitContext ec)
3716                 {
3717                         if (InstanceExpression is This)
3718                                 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3719                         else
3720                                 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3721                                               "(except on the defining type)", Name);
3722                 }
3723
3724                 public override string GetSignatureForError ()
3725                 {
3726                         return TypeManager.CSharpSignature (EventInfo);
3727                 }
3728
3729                 public void EmitAddOrRemove (EmitContext ec, Expression source)
3730                 {
3731                         BinaryDelegate source_del = (BinaryDelegate) source;
3732                         Expression handler = source_del.Right;
3733                         
3734                         Argument arg = new Argument (handler, Argument.AType.Expression);
3735                         ArrayList args = new ArrayList ();
3736                                 
3737                         args.Add (arg);
3738                         
3739                         if (source_del.IsAddition)
3740                                 Invocation.EmitCall (
3741                                         ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3742                         else
3743                                 Invocation.EmitCall (
3744                                         ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3745                 }
3746         }
3747
3748         
3749         public class TemporaryVariable : Expression, IMemoryLocation
3750         {
3751                 LocalInfo li;
3752                 
3753                 public TemporaryVariable (Type type, Location loc)
3754                 {
3755                         this.type = type;
3756                         this.loc = loc;
3757                         eclass = ExprClass.Value;
3758                 }
3759                 
3760                 public override Expression DoResolve (EmitContext ec)
3761                 {
3762                         if (li != null)
3763                                 return this;
3764                         
3765                         TypeExpr te = new TypeExpression (type, loc);
3766                         li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3767                         if (!li.Resolve (ec))
3768                                 return null;
3769                         
3770                         AnonymousContainer am = ec.CurrentAnonymousMethod;
3771                         if ((am != null) && am.IsIterator)
3772                                 ec.CaptureVariable (li);
3773                         
3774                         return this;
3775                 }
3776                 
3777                 public override void Emit (EmitContext ec)
3778                 {
3779                         ILGenerator ig = ec.ig;
3780                         
3781                         if (li.FieldBuilder != null) {
3782                                 ig.Emit (OpCodes.Ldarg_0);
3783                                 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3784                         } else {
3785                                 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3786                         }
3787                 }
3788                 
3789                 public void EmitLoadAddress (EmitContext ec)
3790                 {
3791                         ILGenerator ig = ec.ig;
3792                         
3793                         if (li.FieldBuilder != null) {
3794                                 ig.Emit (OpCodes.Ldarg_0);
3795                                 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3796                         } else {
3797                                 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3798                         }
3799                 }
3800                 
3801                 public void Store (EmitContext ec, Expression right_side)
3802                 {
3803                         if (li.FieldBuilder != null)
3804                                 ec.ig.Emit (OpCodes.Ldarg_0);
3805                         
3806                         right_side.Emit (ec);
3807                         if (li.FieldBuilder != null) {
3808                                 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3809                         } else {
3810                                 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3811                         }
3812                 }
3813                 
3814                 public void EmitThis (EmitContext ec)
3815                 {
3816                         if (li.FieldBuilder != null) {
3817                                 ec.ig.Emit (OpCodes.Ldarg_0);
3818                         }
3819                 }
3820                 
3821                 public void EmitStore (ILGenerator ig)
3822                 {
3823                         if (li.FieldBuilder != null)
3824                                 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3825                         else
3826                                 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3827                 }
3828                 
3829                 public void AddressOf (EmitContext ec, AddressOp mode)
3830                 {
3831                         EmitLoadAddress (ec);
3832                 }
3833         }
3834         
3835 }