2 // ecore.cs: Core of the Expression representation for the intermediate tree.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001, 2002, 2003 Ximian, Inc.
11 namespace Mono.CSharp {
13 using System.Collections;
14 using System.Diagnostics;
15 using System.Reflection;
16 using System.Reflection.Emit;
20 /// The ExprClass class contains the is used to pass the
21 /// classification of an expression (value, variable, namespace,
22 /// type, method group, property access, event access, indexer access,
25 public enum ExprClass : byte {
40 /// This is used to tell Resolve in which types of expressions we're
44 public enum ResolveFlags {
45 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
48 // Returns a type expression.
51 // Returns a method group.
54 // Mask of all the expression class flags.
57 // Disable control flow analysis while resolving the expression.
58 // This is used when resolving the instance expression of a field expression.
59 DisableFlowAnalysis = 8,
61 // Set if this is resolving the first part of a MemberAccess.
64 // Disable control flow analysis _of struct_ while resolving the expression.
65 // This is used when resolving the instance expression of a field expression.
66 DisableStructFlowAnalysis = 32,
71 // This is just as a hint to AddressOf of what will be done with the
74 public enum AddressOp {
81 /// This interface is implemented by variables
83 public interface IMemoryLocation {
85 /// The AddressOf method should generate code that loads
86 /// the address of the object and leaves it on the stack.
88 /// The `mode' argument is used to notify the expression
89 /// of whether this will be used to read from the address or
90 /// write to the address.
92 /// This is just a hint that can be used to provide good error
93 /// reporting, and should have no other side effects.
95 void AddressOf (EmitContext ec, AddressOp mode);
99 /// This interface is implemented by variables
101 public interface IVariable {
102 VariableInfo VariableInfo {
110 /// Base class for expressions
112 public abstract class Expression {
113 public ExprClass eclass;
115 protected Location loc;
119 set { type = value; }
122 public virtual Location Location {
127 /// Utility wrapper routine for Error, just to beautify the code
129 public void Error (int error, string s)
132 Report.Error (error, s);
134 Report.Error (error, loc, s);
137 // Not nice but we have broken hierarchy
138 public virtual void CheckMarshallByRefAccess (Type container) {}
140 public virtual string GetSignatureForError ()
142 return TypeManager.CSharpName (type);
145 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
147 MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
149 must_do_cs1540_check = false; // by default we do not check for this
152 // If only accessible to the current class or children
154 if (ma == MethodAttributes.Private)
155 return invocation_type == mi.DeclaringType ||
156 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
158 if (mi.DeclaringType.Assembly == invocation_type.Assembly) {
159 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
162 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
166 // Family and FamANDAssem require that we derive.
167 // FamORAssem requires that we derive if in different assemblies.
168 if (ma == MethodAttributes.Family ||
169 ma == MethodAttributes.FamANDAssem ||
170 ma == MethodAttributes.FamORAssem) {
171 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
174 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
175 must_do_cs1540_check = true;
184 /// Performs semantic analysis on the Expression
188 /// The Resolve method is invoked to perform the semantic analysis
191 /// The return value is an expression (it can be the
192 /// same expression in some cases) or a new
193 /// expression that better represents this node.
195 /// For example, optimizations of Unary (LiteralInt)
196 /// would return a new LiteralInt with a negated
199 /// If there is an error during semantic analysis,
200 /// then an error should be reported (using Report)
201 /// and a null value should be returned.
203 /// There are two side effects expected from calling
204 /// Resolve(): the the field variable "eclass" should
205 /// be set to any value of the enumeration
206 /// `ExprClass' and the type variable should be set
207 /// to a valid type (this is the type of the
210 public abstract Expression DoResolve (EmitContext ec);
212 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
218 // This is used if the expression should be resolved as a type or namespace name.
219 // the default implementation fails.
221 public virtual FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
227 // This is used to resolve the expression as a type, a null
228 // value will be returned if the expression is not a type
231 public TypeExpr ResolveAsTypeTerminal (EmitContext ec, bool silent)
233 int errors = Report.Errors;
235 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
240 if (fne.eclass != ExprClass.Type) {
241 if (!silent && errors == Report.Errors)
242 fne.Error_UnexpectedKind (null, "type", loc);
246 TypeExpr te = fne as TypeExpr;
248 if (!te.CheckAccessLevel (ec.DeclSpace)) {
249 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
257 public static void ErrorIsInaccesible (Location loc, string name)
259 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
262 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
264 Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
265 + " the qualifier must be of type `{2}' (or derived from it)",
266 TypeManager.GetFullNameSignature (m),
267 TypeManager.CSharpName (qualifier),
268 TypeManager.CSharpName (container));
272 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
274 if (Type.Name == target.Name){
275 Report.ExtraInformation (loc,
277 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
278 Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
283 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
284 GetSignatureForError (), TypeManager.CSharpName (target));
288 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
289 bool b = Convert.ExplicitNumericConversion (e, target) != null;
291 if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
292 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
293 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
297 if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
298 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
299 GetSignatureForError (), TypeManager.CSharpName (target));
303 Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
304 Type == TypeManager.anonymous_method_type ?
305 "anonymous method" : "`" + GetSignatureForError () + "'",
306 TypeManager.CSharpName (target));
309 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
311 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
312 TypeManager.CSharpName (type), name);
315 ResolveFlags ExprClassToResolveFlags ()
319 case ExprClass.Namespace:
320 return ResolveFlags.Type;
322 case ExprClass.MethodGroup:
323 return ResolveFlags.MethodGroup;
325 case ExprClass.Value:
326 case ExprClass.Variable:
327 case ExprClass.PropertyAccess:
328 case ExprClass.EventAccess:
329 case ExprClass.IndexerAccess:
330 return ResolveFlags.VariableOrValue;
333 throw new Exception ("Expression " + GetType () +
334 " ExprClass is Invalid after resolve");
340 /// Resolves an expression and performs semantic analysis on it.
344 /// Currently Resolve wraps DoResolve to perform sanity
345 /// checking and assertion checking on what we expect from Resolve.
347 public Expression Resolve (EmitContext ec, ResolveFlags flags)
349 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
350 return ResolveAsTypeStep (ec, false);
352 bool old_do_flow_analysis = ec.DoFlowAnalysis;
353 bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;
354 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
355 ec.DoFlowAnalysis = false;
356 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
357 ec.OmitStructFlowAnalysis = true;
360 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
361 if (this is SimpleName)
362 e = ((SimpleName) this).DoResolve (ec, intermediate);
367 ec.DoFlowAnalysis = old_do_flow_analysis;
368 ec.OmitStructFlowAnalysis = old_omit_struct_analysis;
373 if ((flags & e.ExprClassToResolveFlags ()) == 0) {
374 e.Error_UnexpectedKind (flags, loc);
378 if (e.type == null && !(e is Namespace)) {
379 throw new Exception (
380 "Expression " + e.GetType () +
381 " did not set its type after Resolve\n" +
382 "called from: " + this.GetType ());
389 /// Resolves an expression and performs semantic analysis on it.
391 public Expression Resolve (EmitContext ec)
393 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
395 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
396 ((MethodGroupExpr) e).ReportUsageError ();
402 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
404 Expression e = Resolve (ec);
408 Constant c = e as Constant;
412 EmptyCast empty = e as EmptyCast;
414 c = empty.Child as Constant;
416 // TODO: not sure about this maybe there is easier way how to use EmptyCast
423 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
428 /// Resolves an expression for LValue assignment
432 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
433 /// checking and assertion checking on what we expect from Resolve
435 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
437 int errors = Report.Errors;
438 Expression e = DoResolveLValue (ec, right_side);
441 if (errors == Report.Errors)
442 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
447 if (e.eclass == ExprClass.Invalid)
448 throw new Exception ("Expression " + e +
449 " ExprClass is Invalid after resolve");
451 if (e.eclass == ExprClass.MethodGroup) {
452 ((MethodGroupExpr) e).ReportUsageError ();
457 throw new Exception ("Expression " + e +
458 " did not set its type after Resolve");
465 /// Emits the code for the expression
469 /// The Emit method is invoked to generate the code
470 /// for the expression.
472 public abstract void Emit (EmitContext ec);
474 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
477 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
481 /// Protected constructor. Only derivate types should
482 /// be able to be created
485 protected Expression ()
487 eclass = ExprClass.Invalid;
492 /// Returns a literalized version of a literal FieldInfo
496 /// The possible return values are:
497 /// IntConstant, UIntConstant
498 /// LongLiteral, ULongConstant
499 /// FloatConstant, DoubleConstant
502 /// The value returned is already resolved.
504 public static Constant Constantify (object v, Type t)
506 if (t == TypeManager.int32_type)
507 return new IntConstant ((int) v, Location.Null);
508 else if (t == TypeManager.uint32_type)
509 return new UIntConstant ((uint) v, Location.Null);
510 else if (t == TypeManager.int64_type)
511 return new LongConstant ((long) v, Location.Null);
512 else if (t == TypeManager.uint64_type)
513 return new ULongConstant ((ulong) v, Location.Null);
514 else if (t == TypeManager.float_type)
515 return new FloatConstant ((float) v, Location.Null);
516 else if (t == TypeManager.double_type)
517 return new DoubleConstant ((double) v, Location.Null);
518 else if (t == TypeManager.string_type)
519 return new StringConstant ((string) v, Location.Null);
520 else if (t == TypeManager.short_type)
521 return new ShortConstant ((short)v, Location.Null);
522 else if (t == TypeManager.ushort_type)
523 return new UShortConstant ((ushort)v, Location.Null);
524 else if (t == TypeManager.sbyte_type)
525 return new SByteConstant ((sbyte)v, Location.Null);
526 else if (t == TypeManager.byte_type)
527 return new ByteConstant ((byte)v, Location.Null);
528 else if (t == TypeManager.char_type)
529 return new CharConstant ((char)v, Location.Null);
530 else if (t == TypeManager.bool_type)
531 return new BoolConstant ((bool) v, Location.Null);
532 else if (t == TypeManager.decimal_type)
533 return new DecimalConstant ((decimal) v, Location.Null);
534 else if (TypeManager.IsEnumType (t)){
535 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
537 real_type = System.Enum.GetUnderlyingType (real_type);
539 Constant e = Constantify (v, real_type);
541 return new EnumConstant (e, t);
542 } else if (v == null && !TypeManager.IsValueType (t))
543 return new NullLiteral (Location.Null);
545 throw new Exception ("Unknown type for constant (" + t +
550 /// Returns a fully formed expression after a MemberLookup
553 public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
556 return new EventExpr ((EventInfo) mi, loc);
557 else if (mi is FieldInfo)
558 return new FieldExpr ((FieldInfo) mi, loc);
559 else if (mi is PropertyInfo)
560 return new PropertyExpr (ec, (PropertyInfo) mi, loc);
561 else if (mi is Type){
562 return new TypeExpression ((System.Type) mi, loc);
568 protected static ArrayList almostMatchedMembers = new ArrayList (4);
571 // FIXME: Probably implement a cache for (t,name,current_access_set)?
573 // This code could use some optimizations, but we need to do some
574 // measurements. For example, we could use a delegate to `flag' when
575 // something can not any longer be a method-group (because it is something
579 // If the return value is an Array, then it is an array of
582 // If the return value is an MemberInfo, it is anything, but a Method
586 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
587 // the arguments here and have MemberLookup return only the methods that
588 // match the argument count/type, unlike we are doing now (we delay this
591 // This is so we can catch correctly attempts to invoke instance methods
592 // from a static body (scan for error 120 in ResolveSimpleName).
595 // FIXME: Potential optimization, have a static ArrayList
598 public static Expression MemberLookup (EmitContext ec, Type queried_type, string name,
599 MemberTypes mt, BindingFlags bf, Location loc)
601 return MemberLookup (ec, ec.ContainerType, null, queried_type, name, mt, bf, loc);
605 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
606 // `qualifier_type' or null to lookup members in the current class.
609 public static Expression MemberLookup (EmitContext ec, Type container_type,
610 Type qualifier_type, Type queried_type,
611 string name, MemberTypes mt,
612 BindingFlags bf, Location loc)
614 almostMatchedMembers.Clear ();
616 MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
617 queried_type, mt, bf, name, almostMatchedMembers);
622 int count = mi.Length;
624 if (mi [0] is MethodBase)
625 return new MethodGroupExpr (mi, loc);
630 return ExprClassFromMemberInfo (ec, mi [0], loc);
633 public const MemberTypes AllMemberTypes =
634 MemberTypes.Constructor |
638 MemberTypes.NestedType |
639 MemberTypes.Property;
641 public const BindingFlags AllBindingFlags =
642 BindingFlags.Public |
643 BindingFlags.Static |
644 BindingFlags.Instance;
646 public static Expression MemberLookup (EmitContext ec, Type queried_type,
647 string name, Location loc)
649 return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
650 AllMemberTypes, AllBindingFlags, loc);
653 public static Expression MemberLookup (EmitContext ec, Type qualifier_type,
654 Type queried_type, string name, Location loc)
656 return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
657 name, AllMemberTypes, AllBindingFlags, loc);
660 public static Expression MethodLookup (EmitContext ec, Type queried_type,
661 string name, Location loc)
663 return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
664 MemberTypes.Method, AllBindingFlags, loc);
668 /// This is a wrapper for MemberLookup that is not used to "probe", but
669 /// to find a final definition. If the final definition is not found, we
670 /// look for private members and display a useful debugging message if we
673 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
674 Type queried_type, string name, Location loc)
676 return MemberLookupFinal (ec, qualifier_type, queried_type, name,
677 AllMemberTypes, AllBindingFlags, loc);
680 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
681 Type queried_type, string name,
682 MemberTypes mt, BindingFlags bf,
687 int errors = Report.Errors;
689 e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
691 if (e == null && errors == Report.Errors)
692 // No errors were reported by MemberLookup, but there was an error.
693 MemberLookupFailed (ec, qualifier_type, queried_type, name, null, true, loc);
698 public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
699 Type queried_type, string name,
700 string class_name, bool complain_if_none_found,
703 if (almostMatchedMembers.Count != 0) {
704 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
705 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
706 for (int j = 0; j < i; ++j) {
707 if (m == almostMatchedMembers [j]) {
715 Type declaring_type = m.DeclaringType;
717 Report.SymbolRelatedToPreviousError (m);
718 if (qualifier_type == null) {
719 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
720 TypeManager.CSharpName (m.DeclaringType),
721 TypeManager.CSharpName (ec.ContainerType));
723 } else if (qualifier_type != ec.ContainerType &&
724 TypeManager.IsNestedFamilyAccessible (ec.ContainerType, declaring_type)) {
725 // Although a derived class can access protected members of
726 // its base class it cannot do so through an instance of the
727 // base class (CS1540). If the qualifier_type is a base of the
728 // ec.ContainerType and the lookup succeeds with the latter one,
729 // then we are in this situation.
730 Error_CannotAccessProtected (loc, m, qualifier_type, ec.ContainerType);
732 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
735 almostMatchedMembers.Clear ();
739 MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
740 AllMemberTypes, AllBindingFlags |
741 BindingFlags.NonPublic, name, null);
743 if (lookup == null) {
744 if (!complain_if_none_found)
747 if (class_name != null)
748 Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
751 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
755 MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
756 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
757 if (name == ".ctor" && ml.Count == 0)
759 Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
763 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
767 /// Returns an expression that can be used to invoke operator true
768 /// on the expression if it exists.
770 static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
772 return GetOperatorTrueOrFalse (ec, e, true, loc);
776 /// Returns an expression that can be used to invoke operator false
777 /// on the expression if it exists.
779 static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
781 return GetOperatorTrueOrFalse (ec, e, false, loc);
784 static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
787 Expression operator_group;
789 operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
790 if (operator_group == null)
793 ArrayList arguments = new ArrayList ();
794 arguments.Add (new Argument (e, Argument.AType.Expression));
795 method = Invocation.OverloadResolve (
796 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
801 return new StaticCallExpr ((MethodInfo) method, arguments, loc);
805 /// Resolves the expression `e' into a boolean expression: either through
806 /// an implicit conversion, or through an `operator true' invocation
808 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
814 if (e.Type == TypeManager.bool_type)
817 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
819 if (converted != null)
823 // If no implicit conversion to bool exists, try using `operator true'
825 converted = Expression.GetOperatorTrue (ec, e, loc);
826 if (converted == null){
827 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
833 public virtual string ExprClassName
837 case ExprClass.Invalid:
839 case ExprClass.Value:
841 case ExprClass.Variable:
843 case ExprClass.Namespace:
847 case ExprClass.MethodGroup:
848 return "method group";
849 case ExprClass.PropertyAccess:
850 return "property access";
851 case ExprClass.EventAccess:
852 return "event access";
853 case ExprClass.IndexerAccess:
854 return "indexer access";
855 case ExprClass.Nothing:
858 throw new Exception ("Should not happen");
863 /// Reports that we were expecting `expr' to be of class `expected'
865 public void Error_UnexpectedKind (EmitContext ec, string expected, Location loc)
867 Error_UnexpectedKind (ec, expected, ExprClassName, loc);
870 public void Error_UnexpectedKind (EmitContext ec, string expected, string was, Location loc)
872 string name = GetSignatureForError ();
874 name = ec.DeclSpace.GetSignatureForError () + '.' + name;
876 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
877 name, was, expected);
880 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
882 string [] valid = new string [4];
885 if ((flags & ResolveFlags.VariableOrValue) != 0) {
886 valid [count++] = "variable";
887 valid [count++] = "value";
890 if ((flags & ResolveFlags.Type) != 0)
891 valid [count++] = "type";
893 if ((flags & ResolveFlags.MethodGroup) != 0)
894 valid [count++] = "method group";
897 valid [count++] = "unknown";
899 StringBuilder sb = new StringBuilder (valid [0]);
900 for (int i = 1; i < count - 1; i++) {
902 sb.Append (valid [i]);
905 sb.Append ("' or `");
906 sb.Append (valid [count - 1]);
909 Report.Error (119, loc,
910 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
913 public static void UnsafeError (Location loc)
915 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
919 // Load the object from the pointer.
921 public static void LoadFromPtr (ILGenerator ig, Type t)
923 if (t == TypeManager.int32_type)
924 ig.Emit (OpCodes.Ldind_I4);
925 else if (t == TypeManager.uint32_type)
926 ig.Emit (OpCodes.Ldind_U4);
927 else if (t == TypeManager.short_type)
928 ig.Emit (OpCodes.Ldind_I2);
929 else if (t == TypeManager.ushort_type)
930 ig.Emit (OpCodes.Ldind_U2);
931 else if (t == TypeManager.char_type)
932 ig.Emit (OpCodes.Ldind_U2);
933 else if (t == TypeManager.byte_type)
934 ig.Emit (OpCodes.Ldind_U1);
935 else if (t == TypeManager.sbyte_type)
936 ig.Emit (OpCodes.Ldind_I1);
937 else if (t == TypeManager.uint64_type)
938 ig.Emit (OpCodes.Ldind_I8);
939 else if (t == TypeManager.int64_type)
940 ig.Emit (OpCodes.Ldind_I8);
941 else if (t == TypeManager.float_type)
942 ig.Emit (OpCodes.Ldind_R4);
943 else if (t == TypeManager.double_type)
944 ig.Emit (OpCodes.Ldind_R8);
945 else if (t == TypeManager.bool_type)
946 ig.Emit (OpCodes.Ldind_I1);
947 else if (t == TypeManager.intptr_type)
948 ig.Emit (OpCodes.Ldind_I);
949 else if (TypeManager.IsEnumType (t)) {
950 if (t == TypeManager.enum_type)
951 ig.Emit (OpCodes.Ldind_Ref);
953 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
954 } else if (t.IsValueType)
955 ig.Emit (OpCodes.Ldobj, t);
956 else if (t.IsPointer)
957 ig.Emit (OpCodes.Ldind_I);
959 ig.Emit (OpCodes.Ldind_Ref);
963 // The stack contains the pointer and the value of type `type'
965 public static void StoreFromPtr (ILGenerator ig, Type type)
967 if (TypeManager.IsEnumType (type))
968 type = TypeManager.EnumToUnderlying (type);
969 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
970 ig.Emit (OpCodes.Stind_I4);
971 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
972 ig.Emit (OpCodes.Stind_I8);
973 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
974 type == TypeManager.ushort_type)
975 ig.Emit (OpCodes.Stind_I2);
976 else if (type == TypeManager.float_type)
977 ig.Emit (OpCodes.Stind_R4);
978 else if (type == TypeManager.double_type)
979 ig.Emit (OpCodes.Stind_R8);
980 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
981 type == TypeManager.bool_type)
982 ig.Emit (OpCodes.Stind_I1);
983 else if (type == TypeManager.intptr_type)
984 ig.Emit (OpCodes.Stind_I);
985 else if (type.IsValueType)
986 ig.Emit (OpCodes.Stobj, type);
988 ig.Emit (OpCodes.Stind_Ref);
992 // Returns the size of type `t' if known, otherwise, 0
994 public static int GetTypeSize (Type t)
996 t = TypeManager.TypeToCoreType (t);
997 if (t == TypeManager.int32_type ||
998 t == TypeManager.uint32_type ||
999 t == TypeManager.float_type)
1001 else if (t == TypeManager.int64_type ||
1002 t == TypeManager.uint64_type ||
1003 t == TypeManager.double_type)
1005 else if (t == TypeManager.byte_type ||
1006 t == TypeManager.sbyte_type ||
1007 t == TypeManager.bool_type)
1009 else if (t == TypeManager.short_type ||
1010 t == TypeManager.char_type ||
1011 t == TypeManager.ushort_type)
1013 else if (t == TypeManager.decimal_type)
1019 public static void Error_NegativeArrayIndex (Location loc)
1021 Report.Error (248, loc, "Cannot create an array with a negative size");
1024 protected void Error_CannotCallAbstractBase (string name)
1026 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1030 // Converts `source' to an int, uint, long or ulong.
1032 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1036 bool old_checked = ec.CheckState;
1037 ec.CheckState = true;
1039 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1040 if (target == null){
1041 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1042 if (target == null){
1043 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1044 if (target == null){
1045 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1047 source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1051 ec.CheckState = old_checked;
1054 // Only positive constants are allowed at compile time
1056 if (target is Constant){
1057 if (target is IntConstant){
1058 if (((IntConstant) target).Value < 0){
1059 Error_NegativeArrayIndex (loc);
1064 if (target is LongConstant){
1065 if (((LongConstant) target).Value < 0){
1066 Error_NegativeArrayIndex (loc);
1079 /// This is just a base class for expressions that can
1080 /// appear on statements (invocations, object creation,
1081 /// assignments, post/pre increment and decrement). The idea
1082 /// being that they would support an extra Emition interface that
1083 /// does not leave a result on the stack.
1085 public abstract class ExpressionStatement : Expression {
1087 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1089 Expression e = Resolve (ec);
1093 ExpressionStatement es = e as ExpressionStatement;
1095 Error (201, "Only assignment, call, increment, decrement and new object " +
1096 "expressions can be used as a statement");
1102 /// Requests the expression to be emitted in a `statement'
1103 /// context. This means that no new value is left on the
1104 /// stack after invoking this method (constrasted with
1105 /// Emit that will always leave a value on the stack).
1107 public abstract void EmitStatement (EmitContext ec);
1111 /// This kind of cast is used to encapsulate the child
1112 /// whose type is child.Type into an expression that is
1113 /// reported to return "return_type". This is used to encapsulate
1114 /// expressions which have compatible types, but need to be dealt
1115 /// at higher levels with.
1117 /// For example, a "byte" expression could be encapsulated in one
1118 /// of these as an "unsigned int". The type for the expression
1119 /// would be "unsigned int".
1122 public class EmptyCast : Expression {
1123 protected Expression child;
1125 public Expression Child {
1131 public EmptyCast (Expression child, Type return_type)
1133 eclass = child.eclass;
1134 loc = child.Location;
1139 public override Expression DoResolve (EmitContext ec)
1141 // This should never be invoked, we are born in fully
1142 // initialized state.
1147 public override void Emit (EmitContext ec)
1153 /// This is a numeric cast to a Decimal
1155 public class CastToDecimal : EmptyCast {
1157 MethodInfo conversion_operator;
1159 public CastToDecimal (Expression child)
1160 : this (child, false)
1164 public CastToDecimal (Expression child, bool find_explicit)
1165 : base (child, TypeManager.decimal_type)
1167 conversion_operator = GetConversionOperator (find_explicit);
1169 if (conversion_operator == null)
1170 throw new InternalErrorException ("Outer conversion routine is out of sync");
1173 // Returns the implicit operator that converts from
1174 // 'child.Type' to System.Decimal.
1175 MethodInfo GetConversionOperator (bool find_explicit)
1177 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1179 MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1180 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1182 foreach (MethodInfo oper in mi) {
1183 ParameterData pd = TypeManager.GetParameterData (oper);
1185 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1191 public override void Emit (EmitContext ec)
1193 ILGenerator ig = ec.ig;
1196 ig.Emit (OpCodes.Call, conversion_operator);
1201 /// This is an explicit numeric cast from a Decimal
1203 public class CastFromDecimal : EmptyCast
1205 static IDictionary operators;
1207 public CastFromDecimal (Expression child, Type return_type)
1208 : base (child, return_type)
1210 if (child.Type != TypeManager.decimal_type)
1211 throw new InternalErrorException (
1212 "The expected type is Decimal, instead it is " + child.Type.FullName);
1215 // Returns the explicit operator that converts from an
1216 // express of type System.Decimal to 'type'.
1217 public Expression Resolve ()
1219 if (operators == null) {
1220 MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1221 TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1222 BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1224 operators = new System.Collections.Specialized.HybridDictionary ();
1225 foreach (MethodInfo oper in all_oper) {
1226 ParameterData pd = TypeManager.GetParameterData (oper);
1227 if (pd.ParameterType (0) == TypeManager.decimal_type)
1228 operators.Add (oper.ReturnType, oper);
1232 return operators.Contains (type) ? this : null;
1235 public override void Emit (EmitContext ec)
1237 ILGenerator ig = ec.ig;
1240 ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1245 // We need to special case this since an empty cast of
1246 // a NullLiteral is still a Constant
1248 public class NullCast : Constant {
1249 public Constant child;
1251 public NullCast (Constant child, Type return_type):
1252 base (Location.Null)
1254 eclass = child.eclass;
1259 override public string AsString ()
1264 public override object GetValue ()
1269 public override Expression DoResolve (EmitContext ec)
1271 // This should never be invoked, we are born in fully
1272 // initialized state.
1277 public override void Emit (EmitContext ec)
1282 public override Constant Increment ()
1284 throw new NotSupportedException ();
1287 public override bool IsDefaultValue {
1293 public override bool IsNegative {
1299 public override Constant Reduce (EmitContext ec, Type target_type)
1301 if (type == target_type)
1302 return child.Reduce (ec, target_type);
1311 /// This class is used to wrap literals which belong inside Enums
1313 public class EnumConstant : Constant {
1314 public Constant Child;
1316 public EnumConstant (Constant child, Type enum_type):
1317 base (child.Location)
1319 eclass = child.eclass;
1324 public override Expression DoResolve (EmitContext ec)
1326 // This should never be invoked, we are born in fully
1327 // initialized state.
1332 public override void Emit (EmitContext ec)
1337 public override string GetSignatureForError()
1339 return TypeManager.CSharpName (Type);
1342 public override object GetValue ()
1344 return Child.GetValue ();
1347 public override object GetTypedValue ()
1349 // FIXME: runtime is not ready to work with just emited enums
1350 if (!RootContext.StdLib) {
1351 return Child.GetValue ();
1354 return System.Enum.ToObject (type, Child.GetValue ());
1357 public override string AsString ()
1359 return Child.AsString ();
1362 public override DoubleConstant ConvertToDouble ()
1364 return Child.ConvertToDouble ();
1367 public override FloatConstant ConvertToFloat ()
1369 return Child.ConvertToFloat ();
1372 public override ULongConstant ConvertToULong ()
1374 return Child.ConvertToULong ();
1377 public override LongConstant ConvertToLong ()
1379 return Child.ConvertToLong ();
1382 public override UIntConstant ConvertToUInt ()
1384 return Child.ConvertToUInt ();
1387 public override IntConstant ConvertToInt ()
1389 return Child.ConvertToInt ();
1392 public override Constant Increment()
1394 return new EnumConstant (Child.Increment (), type);
1397 public override bool IsDefaultValue {
1399 return Child.IsDefaultValue;
1403 public override bool IsZeroInteger {
1404 get { return Child.IsZeroInteger; }
1407 public override bool IsNegative {
1409 return Child.IsNegative;
1413 public override Constant Reduce(EmitContext ec, Type target_type)
1415 if (Child.Type == target_type)
1418 return Child.Reduce (ec, target_type);
1421 public override Constant ToType (Type type, Location loc)
1424 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1425 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1428 if (type.UnderlyingSystemType != Child.Type)
1429 Child = Child.ToType (type.UnderlyingSystemType, loc);
1433 if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){
1434 Error_ValueCannotBeConverted (loc, type, false);
1438 return Child.ToType (type, loc);
1444 /// This kind of cast is used to encapsulate Value Types in objects.
1446 /// The effect of it is to box the value type emitted by the previous
1449 public class BoxedCast : EmptyCast {
1451 public BoxedCast (Expression expr, Type target_type)
1452 : base (expr, target_type)
1454 eclass = ExprClass.Value;
1457 public override Expression DoResolve (EmitContext ec)
1459 // This should never be invoked, we are born in fully
1460 // initialized state.
1465 public override void Emit (EmitContext ec)
1469 ec.ig.Emit (OpCodes.Box, child.Type);
1473 public class UnboxCast : EmptyCast {
1474 public UnboxCast (Expression expr, Type return_type)
1475 : base (expr, return_type)
1479 public override Expression DoResolve (EmitContext ec)
1481 // This should never be invoked, we are born in fully
1482 // initialized state.
1487 public override void Emit (EmitContext ec)
1490 ILGenerator ig = ec.ig;
1493 ig.Emit (OpCodes.Unbox, t);
1495 LoadFromPtr (ig, t);
1500 /// This is used to perform explicit numeric conversions.
1502 /// Explicit numeric conversions might trigger exceptions in a checked
1503 /// context, so they should generate the conv.ovf opcodes instead of
1506 public class ConvCast : EmptyCast {
1507 public enum Mode : byte {
1508 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1510 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1511 U2_I1, U2_U1, U2_I2, U2_CH,
1512 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1513 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1514 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1515 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1516 CH_I1, CH_U1, CH_I2,
1517 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1518 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1523 public ConvCast (Expression child, Type return_type, Mode m)
1524 : base (child, return_type)
1529 public override Expression DoResolve (EmitContext ec)
1531 // This should never be invoked, we are born in fully
1532 // initialized state.
1537 public override string ToString ()
1539 return String.Format ("ConvCast ({0}, {1})", mode, child);
1542 public override void Emit (EmitContext ec)
1544 ILGenerator ig = ec.ig;
1550 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1551 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1552 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1553 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1554 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1556 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1557 case Mode.U1_CH: /* nothing */ break;
1559 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1560 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1561 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1562 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1563 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1564 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1566 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1567 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1568 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1569 case Mode.U2_CH: /* nothing */ break;
1571 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1572 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1573 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1574 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1575 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1576 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1577 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1579 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1580 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1581 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1582 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1583 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1584 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1586 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1587 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1588 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1589 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1590 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1591 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1592 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1593 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1595 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1596 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1597 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1598 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1599 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1600 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1601 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1602 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1604 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1605 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1606 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1608 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1609 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1610 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1611 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1612 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1613 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1614 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1615 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1616 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1618 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1619 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1620 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1621 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1622 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1623 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1624 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1625 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1626 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1627 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1631 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1632 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1633 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1634 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1635 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1637 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1638 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1640 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1641 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1642 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1643 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1644 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1645 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1647 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1648 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1649 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1650 case Mode.U2_CH: /* nothing */ break;
1652 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1653 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1654 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1655 case Mode.I4_U4: /* nothing */ break;
1656 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1657 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1658 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1660 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1661 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1662 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1663 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1664 case Mode.U4_I4: /* nothing */ break;
1665 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1667 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1668 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1669 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1670 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1671 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1672 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1673 case Mode.I8_U8: /* nothing */ break;
1674 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1676 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1677 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1678 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1679 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1680 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1681 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1682 case Mode.U8_I8: /* nothing */ break;
1683 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1685 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1686 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1687 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1689 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1690 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1691 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1692 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1693 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1694 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1695 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1696 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1697 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1699 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1700 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1701 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1702 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1703 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1704 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1705 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1706 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1707 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1708 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1714 public class OpcodeCast : EmptyCast {
1718 public OpcodeCast (Expression child, Type return_type, OpCode op)
1719 : base (child, return_type)
1723 second_valid = false;
1726 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1727 : base (child, return_type)
1732 second_valid = true;
1735 public override Expression DoResolve (EmitContext ec)
1737 // This should never be invoked, we are born in fully
1738 // initialized state.
1743 public override void Emit (EmitContext ec)
1754 /// This kind of cast is used to encapsulate a child and cast it
1755 /// to the class requested
1757 public class ClassCast : EmptyCast {
1758 public ClassCast (Expression child, Type return_type)
1759 : base (child, return_type)
1764 public override Expression DoResolve (EmitContext ec)
1766 // This should never be invoked, we are born in fully
1767 // initialized state.
1772 public override void Emit (EmitContext ec)
1776 ec.ig.Emit (OpCodes.Castclass, type);
1782 /// SimpleName expressions are formed of a single word and only happen at the beginning
1783 /// of a dotted-name.
1785 public class SimpleName : Expression {
1789 public SimpleName (string name, Location l)
1795 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1797 if (ec.IsFieldInitializer)
1798 Report.Error (236, l,
1799 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1802 if (name.LastIndexOf ('.') > 0)
1803 name = name.Substring (name.LastIndexOf ('.') + 1);
1806 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1811 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1813 return resolved_to != null && resolved_to.Type != null &&
1814 resolved_to.Type.Name == Name &&
1815 (ec.DeclSpace.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1818 public override Expression DoResolve (EmitContext ec)
1820 return SimpleNameResolve (ec, null, false);
1823 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1825 return SimpleNameResolve (ec, right_side, false);
1829 public Expression DoResolve (EmitContext ec, bool intermediate)
1831 return SimpleNameResolve (ec, null, intermediate);
1834 public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
1836 int errors = Report.Errors;
1837 FullNamedExpression fne = ec.DeclSpace.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1841 if (silent || errors != Report.Errors)
1844 MemberCore mc = ec.DeclSpace.GetDefinition (Name);
1846 Error_UnexpectedKind (ec, "type", GetMemberType (mc), loc);
1848 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
1854 // TODO: I am still not convinced about this. If someone else will need it
1855 // implement this as virtual property in MemberCore hierarchy
1856 string GetMemberType (MemberCore mc)
1858 if (mc is PropertyBase)
1862 if (mc is FieldBase)
1864 if (mc is MethodCore)
1866 if (mc is EnumMember)
1872 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1878 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
1882 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
1889 /// 7.5.2: Simple Names.
1891 /// Local Variables and Parameters are handled at
1892 /// parse time, so they never occur as SimpleNames.
1894 /// The `intermediate' flag is used by MemberAccess only
1895 /// and it is used to inform us that it is ok for us to
1896 /// avoid the static check, because MemberAccess might end
1897 /// up resolving the Name as a Type name and the access as
1898 /// a static type access.
1900 /// ie: Type Type; .... { Type.GetType (""); }
1902 /// Type is both an instance variable and a Type; Type.GetType
1903 /// is the static method not an instance method of type.
1905 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1907 Expression e = null;
1910 // Stage 1: Performed by the parser (binding to locals or parameters).
1912 Block current_block = ec.CurrentBlock;
1913 if (current_block != null){
1914 LocalInfo vi = current_block.GetLocalInfo (Name);
1916 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
1917 if (right_side != null) {
1918 return var.ResolveLValue (ec, right_side, loc);
1920 ResolveFlags rf = ResolveFlags.VariableOrValue;
1922 rf |= ResolveFlags.DisableFlowAnalysis;
1923 return var.Resolve (ec, rf);
1927 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
1929 if (right_side != null)
1930 return pref.ResolveLValue (ec, right_side, loc);
1932 return pref.Resolve (ec);
1937 // Stage 2: Lookup members
1940 DeclSpace lookup_ds = ec.DeclSpace;
1941 Type almost_matched_type = null;
1942 ArrayList almost_matched = null;
1944 if (lookup_ds.TypeBuilder == null)
1947 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
1951 if (almost_matched == null && almostMatchedMembers.Count > 0) {
1952 almost_matched_type = lookup_ds.TypeBuilder;
1953 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
1956 lookup_ds =lookup_ds.Parent;
1957 } while (lookup_ds != null);
1959 if (e == null && ec.ContainerType != null)
1960 e = MemberLookup (ec, ec.ContainerType, Name, loc);
1963 if (almost_matched == null && almostMatchedMembers.Count > 0) {
1964 almost_matched_type = ec.ContainerType;
1965 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
1967 e = ResolveAsTypeStep (ec, true);
1971 if (almost_matched != null)
1972 almostMatchedMembers = almost_matched;
1973 if (almost_matched_type == null)
1974 almost_matched_type = ec.ContainerType;
1975 MemberLookupFailed (ec, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclSpace.Name, true, loc);
1982 if (e is MemberExpr) {
1983 MemberExpr me = (MemberExpr) e;
1986 if (me.IsInstance) {
1987 if (ec.IsStatic || ec.IsFieldInitializer) {
1989 // Note that an MemberExpr can be both IsInstance and IsStatic.
1990 // An unresolved MethodGroupExpr can contain both kinds of methods
1991 // and each predicate is true if the MethodGroupExpr contains
1992 // at least one of that kind of method.
1996 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
1997 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
1998 return EmptyExpression.Null;
2002 // Pass the buck to MemberAccess and Invocation.
2004 left = EmptyExpression.Null;
2006 left = ec.GetThis (loc);
2009 left = new TypeExpression (ec.ContainerType, loc);
2012 e = me.ResolveMemberAccess (ec, left, loc, null);
2016 me = e as MemberExpr;
2021 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2022 me.InstanceExpression.Type != me.DeclaringType &&
2023 !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
2024 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2025 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2026 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2030 return (right_side != null)
2031 ? me.DoResolveLValue (ec, right_side)
2032 : me.DoResolve (ec);
2038 public override void Emit (EmitContext ec)
2041 // If this is ever reached, then we failed to
2042 // find the name as a namespace
2045 Error (103, "The name `" + Name +
2046 "' does not exist in the class `" +
2047 ec.DeclSpace.Name + "'");
2050 public override string ToString ()
2055 public override string GetSignatureForError ()
2062 /// Represents a namespace or a type. The name of the class was inspired by
2063 /// section 10.8.1 (Fully Qualified Names).
2065 public abstract class FullNamedExpression : Expression {
2066 public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
2071 public abstract string FullName {
2077 /// Expression that evaluates to a type
2079 public abstract class TypeExpr : FullNamedExpression {
2080 override public FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
2082 TypeExpr t = DoResolveAsTypeStep (ec);
2086 eclass = ExprClass.Type;
2090 override public Expression DoResolve (EmitContext ec)
2092 return ResolveAsTypeTerminal (ec, false);
2095 override public void Emit (EmitContext ec)
2097 throw new Exception ("Should never be called");
2100 public virtual bool CheckAccessLevel (DeclSpace ds)
2102 return ds.CheckAccessLevel (Type);
2105 public virtual bool AsAccessible (DeclSpace ds, int flags)
2107 return ds.AsAccessible (Type, flags);
2110 public virtual bool IsClass {
2111 get { return Type.IsClass; }
2114 public virtual bool IsValueType {
2115 get { return Type.IsValueType; }
2118 public virtual bool IsInterface {
2119 get { return Type.IsInterface; }
2122 public virtual bool IsSealed {
2123 get { return Type.IsSealed; }
2126 public virtual bool CanInheritFrom ()
2128 if (Type == TypeManager.enum_type ||
2129 (Type == TypeManager.value_type && RootContext.StdLib) ||
2130 Type == TypeManager.multicast_delegate_type ||
2131 Type == TypeManager.delegate_type ||
2132 Type == TypeManager.array_type)
2138 public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
2140 public Type ResolveType (EmitContext ec)
2142 TypeExpr t = ResolveAsTypeTerminal (ec, false);
2146 if (ec.TestObsoleteMethodUsage) {
2147 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (t.Type);
2148 if (obsolete_attr != null) {
2149 AttributeTester.Report_ObsoleteMessage (obsolete_attr, Name, Location);
2156 public abstract string Name {
2160 public override bool Equals (object obj)
2162 TypeExpr tobj = obj as TypeExpr;
2166 return Type == tobj.Type;
2169 public override int GetHashCode ()
2171 return Type.GetHashCode ();
2174 public override string ToString ()
2181 /// Fully resolved Expression that already evaluated to a type
2183 public class TypeExpression : TypeExpr {
2184 public TypeExpression (Type t, Location l)
2187 eclass = ExprClass.Type;
2191 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2196 public override string Name {
2197 get { return Type.ToString (); }
2200 public override string FullName {
2201 get { return Type.FullName; }
2206 /// Used to create types from a fully qualified name. These are just used
2207 /// by the parser to setup the core types. A TypeLookupExpression is always
2208 /// classified as a type.
2210 public class TypeLookupExpression : TypeExpr {
2213 public TypeLookupExpression (string name)
2218 static readonly char [] dot_array = { '.' };
2219 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2224 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2226 string lookup_name = name;
2227 int pos = name.IndexOf ('.');
2229 rest = name.Substring (pos + 1);
2230 lookup_name = name.Substring (0, pos);
2233 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclSpace, lookup_name, Location.Null);
2235 if (resolved != null && rest != null) {
2236 // Now handle the rest of the the name.
2237 string [] elements = rest.Split (dot_array);
2239 int count = elements.Length;
2241 while (i < count && resolved != null && resolved is Namespace) {
2242 Namespace ns = resolved as Namespace;
2243 element = elements [i++];
2244 lookup_name += "." + element;
2245 resolved = ns.Lookup (ec.DeclSpace, element, Location.Null);
2248 if (resolved != null && resolved is TypeExpr) {
2249 Type t = ((TypeExpr) resolved).Type;
2251 if (!ec.DeclSpace.CheckAccessLevel (t)) {
2253 lookup_name = t.FullName;
2260 t = TypeManager.GetNestedType (t, elements [i++]);
2265 if (resolved == null) {
2266 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2270 if (!(resolved is TypeExpr)) {
2271 resolved.Error_UnexpectedKind (ec, "type", loc);
2275 type = ((TypeExpr) resolved).ResolveType (ec);
2279 public override string Name {
2280 get { return name; }
2283 public override string FullName {
2284 get { return name; }
2288 public class TypeAliasExpression : TypeExpr {
2291 public TypeAliasExpression (TypeExpr texpr, Location l)
2294 loc = texpr.Location;
2296 eclass = ExprClass.Type;
2299 public override string Name {
2300 get { return texpr.Name; }
2303 public override string FullName {
2304 get { return texpr.FullName; }
2307 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2309 Type type = texpr.ResolveType (ec);
2313 return new TypeExpression (type, loc);
2316 public override bool CheckAccessLevel (DeclSpace ds)
2318 return texpr.CheckAccessLevel (ds);
2321 public override bool AsAccessible (DeclSpace ds, int flags)
2323 return texpr.AsAccessible (ds, flags);
2326 public override bool IsClass {
2327 get { return texpr.IsClass; }
2330 public override bool IsValueType {
2331 get { return texpr.IsValueType; }
2334 public override bool IsInterface {
2335 get { return texpr.IsInterface; }
2338 public override bool IsSealed {
2339 get { return texpr.IsSealed; }
2344 /// This class denotes an expression which evaluates to a member
2345 /// of a struct or a class.
2347 public abstract class MemberExpr : Expression
2350 /// The name of this member.
2352 public abstract string Name {
2357 /// Whether this is an instance member.
2359 public abstract bool IsInstance {
2364 /// Whether this is a static member.
2366 public abstract bool IsStatic {
2371 /// The type which declares this member.
2373 public abstract Type DeclaringType {
2378 /// The instance expression associated with this member, if it's a
2379 /// non-static member.
2381 public Expression InstanceExpression;
2383 public static void error176 (Location loc, string name)
2385 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2386 "with an instance reference, qualify it with a type name instead", name);
2389 protected bool CheckIntermediateModification ()
2391 if (!InstanceExpression.Type.IsValueType)
2394 if (InstanceExpression is UnboxCast) {
2395 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
2399 if (!(InstanceExpression is IMemoryLocation)) {
2400 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
2401 InstanceExpression.GetSignatureForError ());
2408 // TODO: possible optimalization
2409 // Cache resolved constant result in FieldBuilder <-> expression map
2410 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2411 SimpleName original)
2415 // original == null || original.Resolve (...) ==> left
2418 if (left is TypeExpr) {
2420 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2428 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2431 error176 (loc, GetSignatureForError ());
2435 InstanceExpression = left;
2440 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2445 if (InstanceExpression == EmptyExpression.Null) {
2446 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2450 if (InstanceExpression.Type.IsValueType) {
2451 if (InstanceExpression is IMemoryLocation) {
2452 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2454 LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
2455 InstanceExpression.Emit (ec);
2457 t.AddressOf (ec, AddressOp.Store);
2460 InstanceExpression.Emit (ec);
2462 if (prepare_for_load)
2463 ec.ig.Emit (OpCodes.Dup);
2468 /// MethodGroup Expression.
2470 /// This is a fully resolved expression that evaluates to a type
2472 public class MethodGroupExpr : MemberExpr {
2473 public MethodBase [] Methods;
2474 bool identical_type_name = false;
2477 public MethodGroupExpr (MemberInfo [] mi, Location l)
2479 Methods = new MethodBase [mi.Length];
2480 mi.CopyTo (Methods, 0);
2481 eclass = ExprClass.MethodGroup;
2482 type = TypeManager.object_type;
2486 public MethodGroupExpr (ArrayList list, Location l)
2488 Methods = new MethodBase [list.Count];
2491 list.CopyTo (Methods, 0);
2493 foreach (MemberInfo m in list){
2494 if (!(m is MethodBase)){
2495 Console.WriteLine ("Name " + m.Name);
2496 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2503 eclass = ExprClass.MethodGroup;
2504 type = TypeManager.object_type;
2507 public override Type DeclaringType {
2510 // The methods are arranged in this order:
2511 // derived type -> base type
2513 return Methods [0].DeclaringType;
2517 public bool IdenticalTypeName {
2519 return identical_type_name;
2523 identical_type_name = value;
2527 public bool IsBase {
2536 public override string GetSignatureForError ()
2538 return TypeManager.CSharpSignature (Methods [0]);
2541 public override string Name {
2543 return Methods [0].Name;
2547 public override bool IsInstance {
2549 foreach (MethodBase mb in Methods)
2557 public override bool IsStatic {
2559 foreach (MethodBase mb in Methods)
2567 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2568 SimpleName original)
2570 if (!(left is TypeExpr) &&
2571 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2572 IdenticalTypeName = true;
2574 return base.ResolveMemberAccess (ec, left, loc, original);
2577 override public Expression DoResolve (EmitContext ec)
2580 InstanceExpression = null;
2582 if (InstanceExpression != null) {
2583 InstanceExpression = InstanceExpression.DoResolve (ec);
2584 if (InstanceExpression == null)
2591 public void ReportUsageError ()
2593 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2594 Name + "()' is referenced without parentheses");
2597 override public void Emit (EmitContext ec)
2599 ReportUsageError ();
2602 bool RemoveMethods (bool keep_static)
2604 ArrayList smethods = new ArrayList ();
2606 foreach (MethodBase mb in Methods){
2607 if (mb.IsStatic == keep_static)
2611 if (smethods.Count == 0)
2614 Methods = new MethodBase [smethods.Count];
2615 smethods.CopyTo (Methods, 0);
2621 /// Removes any instance methods from the MethodGroup, returns
2622 /// false if the resulting set is empty.
2624 public bool RemoveInstanceMethods ()
2626 return RemoveMethods (true);
2630 /// Removes any static methods from the MethodGroup, returns
2631 /// false if the resulting set is empty.
2633 public bool RemoveStaticMethods ()
2635 return RemoveMethods (false);
2640 /// Fully resolved expression that evaluates to a Field
2642 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2643 public readonly FieldInfo FieldInfo;
2644 VariableInfo variable_info;
2646 LocalTemporary temp;
2648 bool in_initializer;
2650 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2653 this.in_initializer = in_initializer;
2656 public FieldExpr (FieldInfo fi, Location l)
2659 eclass = ExprClass.Variable;
2660 type = fi.FieldType;
2664 public override string Name {
2666 return FieldInfo.Name;
2670 public override bool IsInstance {
2672 return !FieldInfo.IsStatic;
2676 public override bool IsStatic {
2678 return FieldInfo.IsStatic;
2682 public override Type DeclaringType {
2684 return FieldInfo.DeclaringType;
2688 public override string GetSignatureForError ()
2690 return TypeManager.GetFullNameSignature (FieldInfo);
2693 public VariableInfo VariableInfo {
2695 return variable_info;
2699 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2700 SimpleName original)
2702 Type t = FieldInfo.FieldType;
2704 if (FieldInfo.IsLiteral || (FieldInfo.IsInitOnly && t == TypeManager.decimal_type)) {
2705 IConstant ic = TypeManager.GetConstant (FieldInfo);
2707 if (FieldInfo.IsLiteral) {
2708 ic = new ExternalConstant (FieldInfo);
2710 ic = ExternalConstant.CreateDecimal (FieldInfo);
2712 return base.ResolveMemberAccess (ec, left, loc, original);
2715 TypeManager.RegisterConstant (FieldInfo, ic);
2718 bool left_is_type = left is TypeExpr;
2719 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
2720 Report.SymbolRelatedToPreviousError (FieldInfo);
2721 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
2725 if (ic.ResolveValue ()) {
2726 if (ec.TestObsoleteMethodUsage)
2727 ic.CheckObsoleteness (loc);
2733 if (t.IsPointer && !ec.InUnsafe) {
2738 return base.ResolveMemberAccess (ec, left, loc, original);
2741 override public Expression DoResolve (EmitContext ec)
2743 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
2744 if (FieldInfo.FieldType is TypeBuilder) {
2745 if (FieldInfo.IsStatic)
2746 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2747 GetSignatureForError ());
2749 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
2750 TypeManager.CSharpName (DeclaringType), Name);
2752 if (FieldInfo.IsStatic)
2753 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2756 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2762 if (!FieldInfo.IsStatic){
2763 if (InstanceExpression == null){
2765 // This can happen when referencing an instance field using
2766 // a fully qualified type expression: TypeName.InstanceField = xxx
2768 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
2772 // Resolve the field's instance expression while flow analysis is turned
2773 // off: when accessing a field "a.b", we must check whether the field
2774 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2775 InstanceExpression = InstanceExpression.Resolve (
2776 ec, ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis);
2777 if (InstanceExpression == null)
2781 if (!in_initializer && !ec.IsFieldInitializer) {
2782 ObsoleteAttribute oa;
2783 FieldBase f = TypeManager.GetField (FieldInfo);
2785 if (ec.TestObsoleteMethodUsage)
2786 f.CheckObsoleteness (loc);
2788 // To be sure that type is external because we do not register generated fields
2789 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
2790 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
2792 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
2796 AnonymousContainer am = ec.CurrentAnonymousMethod;
2798 if (!FieldInfo.IsStatic){
2799 if (!am.IsIterator && (ec.TypeContainer is Struct)){
2800 Report.Error (1673, loc,
2801 "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",
2805 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
2806 ec.CaptureField (this);
2810 // If the instance expression is a local variable or parameter.
2811 IVariable var = InstanceExpression as IVariable;
2812 if ((var == null) || (var.VariableInfo == null))
2815 VariableInfo vi = var.VariableInfo;
2816 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
2819 variable_info = vi.GetSubStruct (FieldInfo.Name);
2823 void Report_AssignToReadonly (bool is_instance)
2828 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
2830 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
2832 Report.Error (is_instance ? 191 : 198, loc, msg);
2835 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2837 IVariable var = InstanceExpression as IVariable;
2838 if ((var != null) && (var.VariableInfo != null))
2839 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
2841 Expression e = DoResolve (ec);
2846 if (!FieldInfo.IsStatic && !CheckIntermediateModification ())
2849 FieldBase fb = TypeManager.GetField (FieldInfo);
2853 if (!FieldInfo.IsInitOnly)
2857 // InitOnly fields can only be assigned in constructors
2860 if (ec.IsConstructor){
2861 if (IsStatic && !ec.IsStatic)
2862 Report_AssignToReadonly (false);
2864 if (ec.ContainerType == FieldInfo.DeclaringType)
2868 Report_AssignToReadonly (!IsStatic);
2873 public override void CheckMarshallByRefAccess (Type container)
2875 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
2876 Report.SymbolRelatedToPreviousError (DeclaringType);
2877 Report.Error (1690, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
2878 GetSignatureForError ());
2882 public bool VerifyFixed ()
2884 IVariable variable = InstanceExpression as IVariable;
2885 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
2886 // We defer the InstanceExpression check after the variable check to avoid a
2887 // separate null check on InstanceExpression.
2888 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
2891 public override int GetHashCode()
2893 return FieldInfo.GetHashCode ();
2896 public override bool Equals (object obj)
2898 FieldExpr fe = obj as FieldExpr;
2902 if (FieldInfo != fe.FieldInfo)
2905 if (InstanceExpression == null || fe.InstanceExpression == null)
2908 return InstanceExpression.Equals (fe.InstanceExpression);
2911 public void Emit (EmitContext ec, bool leave_copy)
2913 ILGenerator ig = ec.ig;
2914 bool is_volatile = false;
2916 if (FieldInfo is FieldBuilder){
2917 FieldBase f = TypeManager.GetField (FieldInfo);
2919 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
2922 f.SetMemberIsUsed ();
2926 if (FieldInfo.IsStatic){
2928 ig.Emit (OpCodes.Volatile);
2930 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2933 EmitInstance (ec, false);
2936 ig.Emit (OpCodes.Volatile);
2938 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
2941 ig.Emit (OpCodes.Ldflda, FieldInfo);
2942 ig.Emit (OpCodes.Ldflda, ff.Element);
2945 ig.Emit (OpCodes.Ldfld, FieldInfo);
2950 ec.ig.Emit (OpCodes.Dup);
2951 if (!FieldInfo.IsStatic) {
2952 temp = new LocalTemporary (ec, this.Type);
2958 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
2960 FieldAttributes fa = FieldInfo.Attributes;
2961 bool is_static = (fa & FieldAttributes.Static) != 0;
2962 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
2963 ILGenerator ig = ec.ig;
2964 prepared = prepare_for_load;
2966 if (is_readonly && !ec.IsConstructor){
2967 Report_AssignToReadonly (!is_static);
2971 EmitInstance (ec, prepare_for_load);
2975 ec.ig.Emit (OpCodes.Dup);
2976 if (!FieldInfo.IsStatic) {
2977 temp = new LocalTemporary (ec, this.Type);
2982 if (FieldInfo is FieldBuilder){
2983 FieldBase f = TypeManager.GetField (FieldInfo);
2985 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
2986 ig.Emit (OpCodes.Volatile);
2993 ig.Emit (OpCodes.Stsfld, FieldInfo);
2995 ig.Emit (OpCodes.Stfld, FieldInfo);
3001 public override void Emit (EmitContext ec)
3006 public void AddressOf (EmitContext ec, AddressOp mode)
3008 ILGenerator ig = ec.ig;
3010 if (FieldInfo is FieldBuilder){
3011 FieldBase f = TypeManager.GetField (FieldInfo);
3013 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3014 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3015 f.GetSignatureForError ());
3019 if ((mode & AddressOp.Store) != 0)
3021 if ((mode & AddressOp.Load) != 0)
3022 f.SetMemberIsUsed ();
3027 // Handle initonly fields specially: make a copy and then
3028 // get the address of the copy.
3031 if (FieldInfo.IsInitOnly){
3033 if (ec.IsConstructor){
3034 if (FieldInfo.IsStatic){
3046 local = ig.DeclareLocal (type);
3047 ig.Emit (OpCodes.Stloc, local);
3048 ig.Emit (OpCodes.Ldloca, local);
3053 if (FieldInfo.IsStatic){
3054 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3056 EmitInstance (ec, false);
3057 ig.Emit (OpCodes.Ldflda, FieldInfo);
3063 // A FieldExpr whose address can not be taken
3065 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3066 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3070 public new void AddressOf (EmitContext ec, AddressOp mode)
3072 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3077 /// Expression that evaluates to a Property. The Assign class
3078 /// might set the `Value' expression if we are in an assignment.
3080 /// This is not an LValue because we need to re-write the expression, we
3081 /// can not take data from the stack and store it.
3083 public class PropertyExpr : MemberExpr, IAssignMethod {
3084 public readonly PropertyInfo PropertyInfo;
3087 // This is set externally by the `BaseAccess' class
3090 MethodInfo getter, setter;
3095 LocalTemporary temp;
3098 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3100 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
3103 eclass = ExprClass.PropertyAccess;
3107 type = TypeManager.TypeToCoreType (pi.PropertyType);
3109 ResolveAccessors (ec);
3112 public override string Name {
3114 return PropertyInfo.Name;
3118 public override bool IsInstance {
3124 public override bool IsStatic {
3130 public override Type DeclaringType {
3132 return PropertyInfo.DeclaringType;
3136 public override string GetSignatureForError ()
3138 return TypeManager.GetFullNameSignature (PropertyInfo);
3141 void FindAccessors (Type invocation_type)
3143 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3144 BindingFlags.Static | BindingFlags.Instance |
3145 BindingFlags.DeclaredOnly;
3147 Type current = PropertyInfo.DeclaringType;
3148 for (; current != null; current = current.BaseType) {
3149 MemberInfo[] group = TypeManager.MemberLookup (
3150 invocation_type, invocation_type, current,
3151 MemberTypes.Property, flags, PropertyInfo.Name, null);
3156 if (group.Length != 1)
3157 // Oooops, can this ever happen ?
3160 PropertyInfo pi = (PropertyInfo) group [0];
3163 getter = pi.GetGetMethod (true);
3166 setter = pi.GetSetMethod (true);
3168 MethodInfo accessor = getter != null ? getter : setter;
3170 if (!accessor.IsVirtual)
3176 // We also perform the permission checking here, as the PropertyInfo does not
3177 // hold the information for the accessibility of its setter/getter
3179 void ResolveAccessors (EmitContext ec)
3181 FindAccessors (ec.ContainerType);
3183 if (getter != null) {
3184 IMethodData md = TypeManager.GetMethod (getter);
3186 md.SetMemberIsUsed ();
3188 AccessorTable [getter] = PropertyInfo;
3189 is_static = getter.IsStatic;
3192 if (setter != null) {
3193 IMethodData md = TypeManager.GetMethod (setter);
3195 md.SetMemberIsUsed ();
3197 AccessorTable [setter] = PropertyInfo;
3198 is_static = setter.IsStatic;
3202 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3205 InstanceExpression = null;
3209 if (InstanceExpression == null) {
3210 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3214 InstanceExpression = InstanceExpression.DoResolve (ec);
3215 if (InstanceExpression == null)
3218 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3220 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3221 InstanceExpression.Type != ec.ContainerType &&
3222 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3223 InstanceExpression.Type.IsSubclassOf (PropertyInfo.DeclaringType)) {
3224 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3231 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3233 // TODO: correctly we should compare arguments but it will lead to bigger changes
3234 if (mi is MethodBuilder) {
3235 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3239 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3241 ParameterData iparams = TypeManager.GetParameterData (mi);
3242 sig.Append (getter ? "get_" : "set_");
3244 sig.Append (iparams.GetSignatureForError ());
3246 Report.SymbolRelatedToPreviousError (mi);
3247 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3248 Name, sig.ToString ());
3251 override public Expression DoResolve (EmitContext ec)
3256 if (getter != null){
3257 if (TypeManager.GetParameterData (getter).Count != 0){
3258 Error_PropertyNotFound (getter, true);
3263 if (getter == null){
3265 // The following condition happens if the PropertyExpr was
3266 // created, but is invalid (ie, the property is inaccessible),
3267 // and we did not want to embed the knowledge about this in
3268 // the caller routine. This only avoids double error reporting.
3273 if (InstanceExpression != EmptyExpression.Null) {
3274 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3275 TypeManager.GetFullNameSignature (PropertyInfo));
3280 bool must_do_cs1540_check = false;
3281 if (getter != null &&
3282 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3283 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3284 if (pm != null && pm.HasCustomAccessModifier) {
3285 Report.SymbolRelatedToPreviousError (pm);
3286 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3287 TypeManager.CSharpSignature (getter));
3290 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3294 if (!InstanceResolve (ec, must_do_cs1540_check))
3298 // Only base will allow this invocation to happen.
3300 if (IsBase && getter.IsAbstract) {
3301 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3305 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3315 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3317 if (setter == null){
3319 // The following condition happens if the PropertyExpr was
3320 // created, but is invalid (ie, the property is inaccessible),
3321 // and we did not want to embed the knowledge about this in
3322 // the caller routine. This only avoids double error reporting.
3327 Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)",
3328 TypeManager.GetFullNameSignature (PropertyInfo));
3332 if (TypeManager.GetParameterData (setter).Count != 1){
3333 Error_PropertyNotFound (setter, false);
3337 bool must_do_cs1540_check;
3338 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3339 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3340 if (pm != null && pm.HasCustomAccessModifier) {
3341 Report.SymbolRelatedToPreviousError (pm);
3342 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3343 TypeManager.CSharpSignature (setter));
3346 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3350 if (!InstanceResolve (ec, must_do_cs1540_check))
3354 // Only base will allow this invocation to happen.
3356 if (IsBase && setter.IsAbstract){
3357 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3362 // Check that we are not making changes to a temporary memory location
3364 if (InstanceExpression != null && !CheckIntermediateModification ())
3370 public override void Emit (EmitContext ec)
3375 public void Emit (EmitContext ec, bool leave_copy)
3378 // Special case: length of single dimension array property is turned into ldlen
3380 if ((getter == TypeManager.system_int_array_get_length) ||
3381 (getter == TypeManager.int_array_get_length)){
3382 Type iet = InstanceExpression.Type;
3385 // System.Array.Length can be called, but the Type does not
3386 // support invoking GetArrayRank, so test for that case first
3388 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3390 EmitInstance (ec, false);
3391 ec.ig.Emit (OpCodes.Ldlen);
3392 ec.ig.Emit (OpCodes.Conv_I4);
3397 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3400 ec.ig.Emit (OpCodes.Dup);
3402 temp = new LocalTemporary (ec, this.Type);
3409 // Implements the IAssignMethod interface for assignments
3411 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3413 Expression my_source = source;
3415 prepared = prepare_for_load;
3420 ec.ig.Emit (OpCodes.Dup);
3422 temp = new LocalTemporary (ec, this.Type);
3426 } else if (leave_copy) {
3429 temp = new LocalTemporary (ec, this.Type);
3435 ArrayList args = new ArrayList (1);
3436 args.Add (new Argument (my_source, Argument.AType.Expression));
3438 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3446 /// Fully resolved expression that evaluates to an Event
3448 public class EventExpr : MemberExpr {
3449 public readonly EventInfo EventInfo;
3452 MethodInfo add_accessor, remove_accessor;
3454 public EventExpr (EventInfo ei, Location loc)
3458 eclass = ExprClass.EventAccess;
3460 add_accessor = TypeManager.GetAddMethod (ei);
3461 remove_accessor = TypeManager.GetRemoveMethod (ei);
3463 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3466 if (EventInfo is MyEventBuilder){
3467 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3468 type = eb.EventType;
3471 type = EventInfo.EventHandlerType;
3474 public override string Name {
3476 return EventInfo.Name;
3480 public override bool IsInstance {
3486 public override bool IsStatic {
3492 public override Type DeclaringType {
3494 return EventInfo.DeclaringType;
3498 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3499 SimpleName original)
3502 // If the event is local to this class, we transform ourselves into a FieldExpr
3505 if (EventInfo.DeclaringType == ec.ContainerType ||
3506 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3507 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3510 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc);
3513 Report.Error (-200, loc, "Internal error!!");
3517 InstanceExpression = null;
3519 return ml.ResolveMemberAccess (ec, left, loc, original);
3523 return base.ResolveMemberAccess (ec, left, loc, original);
3527 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3530 InstanceExpression = null;
3534 if (InstanceExpression == null) {
3535 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3539 InstanceExpression = InstanceExpression.DoResolve (ec);
3540 if (InstanceExpression == null)
3544 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3545 // However, in the Event case, we reported a CS0122 instead.
3547 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) {
3548 if ((InstanceExpression.Type != ec.ContainerType) &&
3549 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3550 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3558 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3560 return DoResolve (ec);
3563 public override Expression DoResolve (EmitContext ec)
3565 bool must_do_cs1540_check;
3566 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3567 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3568 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3572 if (!InstanceResolve (ec, must_do_cs1540_check))
3578 public override void Emit (EmitContext ec)
3580 if (InstanceExpression is This)
3581 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3583 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3584 "(except on the defining type)", Name);
3587 public override string GetSignatureForError ()
3589 return TypeManager.CSharpSignature (EventInfo);
3592 public void EmitAddOrRemove (EmitContext ec, Expression source)
3594 BinaryDelegate source_del = (BinaryDelegate) source;
3595 Expression handler = source_del.Right;
3597 Argument arg = new Argument (handler, Argument.AType.Expression);
3598 ArrayList args = new ArrayList ();
3602 if (source_del.IsAddition)
3603 Invocation.EmitCall (
3604 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3606 Invocation.EmitCall (
3607 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3612 public class TemporaryVariable : Expression, IMemoryLocation
3616 public TemporaryVariable (Type type, Location loc)
3620 eclass = ExprClass.Value;
3623 public override Expression DoResolve (EmitContext ec)
3628 TypeExpr te = new TypeExpression (type, loc);
3629 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3630 if (!li.Resolve (ec))
3633 AnonymousContainer am = ec.CurrentAnonymousMethod;
3634 if ((am != null) && am.IsIterator)
3635 ec.CaptureVariable (li);
3640 public override void Emit (EmitContext ec)
3642 ILGenerator ig = ec.ig;
3644 if (li.FieldBuilder != null) {
3645 ig.Emit (OpCodes.Ldarg_0);
3646 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3648 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3652 public void EmitLoadAddress (EmitContext ec)
3654 ILGenerator ig = ec.ig;
3656 if (li.FieldBuilder != null) {
3657 ig.Emit (OpCodes.Ldarg_0);
3658 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3660 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3664 public void Store (EmitContext ec, Expression right_side)
3666 if (li.FieldBuilder != null)
3667 ec.ig.Emit (OpCodes.Ldarg_0);
3669 right_side.Emit (ec);
3670 if (li.FieldBuilder != null) {
3671 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3673 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3677 public void EmitThis (EmitContext ec)
3679 if (li.FieldBuilder != null) {
3680 ec.ig.Emit (OpCodes.Ldarg_0);
3684 public void EmitStore (ILGenerator ig)
3686 if (li.FieldBuilder != null)
3687 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3689 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3692 public void AddressOf (EmitContext ec, AddressOp mode)
3694 EmitLoadAddress (ec);