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);
138 /// Utility wrapper routine for Warning, just to beautify the code
140 public void Warning (int code, string format, params object[] args)
142 Report.Warning (code, loc, format, args);
145 // Not nice but we have broken hierarchy
146 public virtual void CheckMarshallByRefAccess (Type container) {}
148 public virtual string GetSignatureForError ()
150 return TypeManager.CSharpName (type);
153 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
155 MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
157 must_do_cs1540_check = false; // by default we do not check for this
160 // If only accessible to the current class or children
162 if (ma == MethodAttributes.Private)
163 return invocation_type == mi.DeclaringType ||
164 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
166 if (mi.DeclaringType.Assembly == invocation_type.Assembly) {
167 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
170 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
174 // Family and FamANDAssem require that we derive.
175 // FamORAssem requires that we derive if in different assemblies.
176 if (ma == MethodAttributes.Family ||
177 ma == MethodAttributes.FamANDAssem ||
178 ma == MethodAttributes.FamORAssem) {
179 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
182 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
183 must_do_cs1540_check = true;
192 /// Performs semantic analysis on the Expression
196 /// The Resolve method is invoked to perform the semantic analysis
199 /// The return value is an expression (it can be the
200 /// same expression in some cases) or a new
201 /// expression that better represents this node.
203 /// For example, optimizations of Unary (LiteralInt)
204 /// would return a new LiteralInt with a negated
207 /// If there is an error during semantic analysis,
208 /// then an error should be reported (using Report)
209 /// and a null value should be returned.
211 /// There are two side effects expected from calling
212 /// Resolve(): the the field variable "eclass" should
213 /// be set to any value of the enumeration
214 /// `ExprClass' and the type variable should be set
215 /// to a valid type (this is the type of the
218 public abstract Expression DoResolve (EmitContext ec);
220 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
226 // This is used if the expression should be resolved as a type or namespace name.
227 // the default implementation fails.
229 public virtual FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
235 // This is used to resolve the expression as a type, a null
236 // value will be returned if the expression is not a type
239 public TypeExpr ResolveAsTypeTerminal (EmitContext ec, bool silent)
241 int errors = Report.Errors;
243 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
248 if (fne.eclass != ExprClass.Type) {
249 if (!silent && errors == Report.Errors)
250 fne.Error_UnexpectedKind (null, "type", loc);
254 TypeExpr te = fne as TypeExpr;
256 if (!te.CheckAccessLevel (ec.DeclSpace)) {
257 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
265 public static void ErrorIsInaccesible (Location loc, string name)
267 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
270 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
272 if (Type.Name == target.Name){
273 Report.ExtraInformation (loc,
275 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
276 Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
281 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
282 GetSignatureForError (), TypeManager.CSharpName (target));
286 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
287 bool b = Convert.ExplicitNumericConversion (e, target) != null;
289 if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
290 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
291 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
295 if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
296 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
297 GetSignatureForError (), TypeManager.CSharpName (target));
301 Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
302 Type == TypeManager.anonymous_method_type ?
303 "anonymous method" : "`" + GetSignatureForError () + "'",
304 TypeManager.CSharpName (target));
307 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
309 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
310 TypeManager.CSharpName (type), name);
313 ResolveFlags ExprClassToResolveFlags ()
317 case ExprClass.Namespace:
318 return ResolveFlags.Type;
320 case ExprClass.MethodGroup:
321 return ResolveFlags.MethodGroup;
323 case ExprClass.Value:
324 case ExprClass.Variable:
325 case ExprClass.PropertyAccess:
326 case ExprClass.EventAccess:
327 case ExprClass.IndexerAccess:
328 return ResolveFlags.VariableOrValue;
331 throw new Exception ("Expression " + GetType () +
332 " ExprClass is Invalid after resolve");
338 /// Resolves an expression and performs semantic analysis on it.
342 /// Currently Resolve wraps DoResolve to perform sanity
343 /// checking and assertion checking on what we expect from Resolve.
345 public Expression Resolve (EmitContext ec, ResolveFlags flags)
347 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
348 return ResolveAsTypeStep (ec, false);
350 bool old_do_flow_analysis = ec.DoFlowAnalysis;
351 bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;
352 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
353 ec.DoFlowAnalysis = false;
354 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
355 ec.OmitStructFlowAnalysis = true;
358 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
359 if (this is SimpleName)
360 e = ((SimpleName) this).DoResolve (ec, intermediate);
365 ec.DoFlowAnalysis = old_do_flow_analysis;
366 ec.OmitStructFlowAnalysis = old_omit_struct_analysis;
371 if ((flags & e.ExprClassToResolveFlags ()) == 0) {
372 e.Error_UnexpectedKind (flags, loc);
376 if (e.type == null && !(e is Namespace)) {
377 throw new Exception (
378 "Expression " + e.GetType () +
379 " did not set its type after Resolve\n" +
380 "called from: " + this.GetType ());
387 /// Resolves an expression and performs semantic analysis on it.
389 public Expression Resolve (EmitContext ec)
391 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
393 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
394 ((MethodGroupExpr) e).ReportUsageError ();
400 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
402 Expression e = Resolve (ec);
404 Constant c = e as Constant;
408 EmptyCast empty = e as EmptyCast;
410 c = empty.Child as Constant;
412 // TODO: not sure about this maybe there is easier way how to use EmptyCast
421 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
426 /// Resolves an expression for LValue assignment
430 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
431 /// checking and assertion checking on what we expect from Resolve
433 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
435 int errors = Report.Errors;
436 Expression e = DoResolveLValue (ec, right_side);
439 if (errors == Report.Errors)
440 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
445 if (e.eclass == ExprClass.Invalid)
446 throw new Exception ("Expression " + e +
447 " ExprClass is Invalid after resolve");
449 if (e.eclass == ExprClass.MethodGroup) {
450 ((MethodGroupExpr) e).ReportUsageError ();
455 throw new Exception ("Expression " + e +
456 " did not set its type after Resolve");
463 /// Emits the code for the expression
467 /// The Emit method is invoked to generate the code
468 /// for the expression.
470 public abstract void Emit (EmitContext ec);
472 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
475 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
479 /// Protected constructor. Only derivate types should
480 /// be able to be created
483 protected Expression ()
485 eclass = ExprClass.Invalid;
490 /// Returns a literalized version of a literal FieldInfo
494 /// The possible return values are:
495 /// IntConstant, UIntConstant
496 /// LongLiteral, ULongConstant
497 /// FloatConstant, DoubleConstant
500 /// The value returned is already resolved.
502 public static Constant Constantify (object v, Type t)
504 if (t == TypeManager.int32_type)
505 return new IntConstant ((int) v, Location.Null);
506 else if (t == TypeManager.uint32_type)
507 return new UIntConstant ((uint) v, Location.Null);
508 else if (t == TypeManager.int64_type)
509 return new LongConstant ((long) v, Location.Null);
510 else if (t == TypeManager.uint64_type)
511 return new ULongConstant ((ulong) v, Location.Null);
512 else if (t == TypeManager.float_type)
513 return new FloatConstant ((float) v, Location.Null);
514 else if (t == TypeManager.double_type)
515 return new DoubleConstant ((double) v, Location.Null);
516 else if (t == TypeManager.string_type)
517 return new StringConstant ((string) v, Location.Null);
518 else if (t == TypeManager.short_type)
519 return new ShortConstant ((short)v, Location.Null);
520 else if (t == TypeManager.ushort_type)
521 return new UShortConstant ((ushort)v, Location.Null);
522 else if (t == TypeManager.sbyte_type)
523 return new SByteConstant ((sbyte)v, Location.Null);
524 else if (t == TypeManager.byte_type)
525 return new ByteConstant ((byte)v, Location.Null);
526 else if (t == TypeManager.char_type)
527 return new CharConstant ((char)v, Location.Null);
528 else if (t == TypeManager.bool_type)
529 return new BoolConstant ((bool) v, Location.Null);
530 else if (t == TypeManager.decimal_type)
531 return new DecimalConstant ((decimal) v, Location.Null);
532 else if (TypeManager.IsEnumType (t)){
533 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
535 real_type = System.Enum.GetUnderlyingType (real_type);
537 Constant e = Constantify (v, real_type);
539 return new EnumConstant (e, t);
540 } else if (v == null && !TypeManager.IsValueType (t))
541 return new NullLiteral (Location.Null);
543 throw new Exception ("Unknown type for constant (" + t +
548 /// Returns a fully formed expression after a MemberLookup
551 public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
554 return new EventExpr ((EventInfo) mi, loc);
555 else if (mi is FieldInfo)
556 return new FieldExpr ((FieldInfo) mi, loc);
557 else if (mi is PropertyInfo)
558 return new PropertyExpr (ec, (PropertyInfo) mi, loc);
559 else if (mi is Type){
560 return new TypeExpression ((System.Type) mi, loc);
566 protected static ArrayList almostMatchedMembers = new ArrayList (4);
569 // FIXME: Probably implement a cache for (t,name,current_access_set)?
571 // This code could use some optimizations, but we need to do some
572 // measurements. For example, we could use a delegate to `flag' when
573 // something can not any longer be a method-group (because it is something
577 // If the return value is an Array, then it is an array of
580 // If the return value is an MemberInfo, it is anything, but a Method
584 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
585 // the arguments here and have MemberLookup return only the methods that
586 // match the argument count/type, unlike we are doing now (we delay this
589 // This is so we can catch correctly attempts to invoke instance methods
590 // from a static body (scan for error 120 in ResolveSimpleName).
593 // FIXME: Potential optimization, have a static ArrayList
596 public static Expression MemberLookup (EmitContext ec, Type queried_type, string name,
597 MemberTypes mt, BindingFlags bf, Location loc)
599 return MemberLookup (ec, ec.ContainerType, null, queried_type, name, mt, bf, loc);
603 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
604 // `qualifier_type' or null to lookup members in the current class.
607 public static Expression MemberLookup (EmitContext ec, Type container_type,
608 Type qualifier_type, Type queried_type,
609 string name, MemberTypes mt,
610 BindingFlags bf, Location loc)
612 almostMatchedMembers.Clear ();
614 MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
615 queried_type, mt, bf, name, almostMatchedMembers);
620 int count = mi.Length;
622 if (mi [0] is MethodBase)
623 return new MethodGroupExpr (mi, loc);
628 return ExprClassFromMemberInfo (ec, mi [0], loc);
631 public const MemberTypes AllMemberTypes =
632 MemberTypes.Constructor |
636 MemberTypes.NestedType |
637 MemberTypes.Property;
639 public const BindingFlags AllBindingFlags =
640 BindingFlags.Public |
641 BindingFlags.Static |
642 BindingFlags.Instance;
644 public static Expression MemberLookup (EmitContext ec, Type queried_type,
645 string name, Location loc)
647 return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
648 AllMemberTypes, AllBindingFlags, loc);
651 public static Expression MemberLookup (EmitContext ec, Type qualifier_type,
652 Type queried_type, string name, Location loc)
654 return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
655 name, AllMemberTypes, AllBindingFlags, loc);
658 public static Expression MethodLookup (EmitContext ec, Type queried_type,
659 string name, Location loc)
661 return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
662 MemberTypes.Method, AllBindingFlags, loc);
666 /// This is a wrapper for MemberLookup that is not used to "probe", but
667 /// to find a final definition. If the final definition is not found, we
668 /// look for private members and display a useful debugging message if we
671 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
672 Type queried_type, string name, Location loc)
674 return MemberLookupFinal (ec, qualifier_type, queried_type, name,
675 AllMemberTypes, AllBindingFlags, loc);
678 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
679 Type queried_type, string name,
680 MemberTypes mt, BindingFlags bf,
685 int errors = Report.Errors;
687 e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
689 if (e == null && errors == Report.Errors)
690 // No errors were reported by MemberLookup, but there was an error.
691 MemberLookupFailed (ec, qualifier_type, queried_type, name, null, true, loc);
696 public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
697 Type queried_type, string name,
698 string class_name, bool complain_if_none_found,
701 if (almostMatchedMembers.Count != 0) {
702 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
703 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
704 for (int j = 0; j < i; ++j) {
705 if (m == almostMatchedMembers [j]) {
713 Type declaring_type = m.DeclaringType;
715 Report.SymbolRelatedToPreviousError (m);
716 if (qualifier_type == null) {
717 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
718 TypeManager.CSharpName (m.DeclaringType),
719 TypeManager.CSharpName (ec.ContainerType));
721 } else if (qualifier_type != ec.ContainerType &&
722 TypeManager.IsNestedFamilyAccessible (ec.ContainerType, declaring_type)) {
723 // Although a derived class can access protected members of
724 // its base class it cannot do so through an instance of the
725 // base class (CS1540). If the qualifier_type is a base of the
726 // ec.ContainerType and the lookup succeeds with the latter one,
727 // then we are in this situation.
728 Report.Error (1540, loc,
729 "Cannot access protected member `{0}' via a qualifier of type `{1}';"
730 + " the qualifier must be of type `{2}' (or derived from it)",
731 TypeManager.GetFullNameSignature (m),
732 TypeManager.CSharpName (qualifier_type),
733 TypeManager.CSharpName (ec.ContainerType));
735 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
738 almostMatchedMembers.Clear ();
742 MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
743 AllMemberTypes, AllBindingFlags |
744 BindingFlags.NonPublic, name, null);
746 if (lookup == null) {
747 if (!complain_if_none_found)
750 if (class_name != null)
751 Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
754 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
758 MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
759 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
760 if (name == ".ctor" && ml.Count == 0)
762 Report.Error (143, loc, String.Format ("The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type)));
766 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
770 /// Returns an expression that can be used to invoke operator true
771 /// on the expression if it exists.
773 static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
775 return GetOperatorTrueOrFalse (ec, e, true, loc);
779 /// Returns an expression that can be used to invoke operator false
780 /// on the expression if it exists.
782 static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
784 return GetOperatorTrueOrFalse (ec, e, false, loc);
787 static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
790 Expression operator_group;
792 operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
793 if (operator_group == null)
796 ArrayList arguments = new ArrayList ();
797 arguments.Add (new Argument (e, Argument.AType.Expression));
798 method = Invocation.OverloadResolve (
799 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
804 return new StaticCallExpr ((MethodInfo) method, arguments, loc);
808 /// Resolves the expression `e' into a boolean expression: either through
809 /// an implicit conversion, or through an `operator true' invocation
811 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
817 if (e.Type == TypeManager.bool_type)
820 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
822 if (converted != null)
826 // If no implicit conversion to bool exists, try using `operator true'
828 converted = Expression.GetOperatorTrue (ec, e, loc);
829 if (converted == null){
830 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
836 public virtual string ExprClassName
840 case ExprClass.Invalid:
842 case ExprClass.Value:
844 case ExprClass.Variable:
846 case ExprClass.Namespace:
850 case ExprClass.MethodGroup:
851 return "method group";
852 case ExprClass.PropertyAccess:
853 return "property access";
854 case ExprClass.EventAccess:
855 return "event access";
856 case ExprClass.IndexerAccess:
857 return "indexer access";
858 case ExprClass.Nothing:
861 throw new Exception ("Should not happen");
866 /// Reports that we were expecting `expr' to be of class `expected'
868 public void Error_UnexpectedKind (EmitContext ec, string expected, Location loc)
870 Error_UnexpectedKind (ec, expected, ExprClassName, loc);
873 public void Error_UnexpectedKind (EmitContext ec, string expected, string was, Location loc)
875 string name = GetSignatureForError ();
877 name = ec.DeclSpace.GetSignatureForError () + '.' + name;
879 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
880 name, was, expected);
883 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
885 string [] valid = new string [4];
888 if ((flags & ResolveFlags.VariableOrValue) != 0) {
889 valid [count++] = "variable";
890 valid [count++] = "value";
893 if ((flags & ResolveFlags.Type) != 0)
894 valid [count++] = "type";
896 if ((flags & ResolveFlags.MethodGroup) != 0)
897 valid [count++] = "method group";
900 valid [count++] = "unknown";
902 StringBuilder sb = new StringBuilder (valid [0]);
903 for (int i = 1; i < count - 1; i++) {
905 sb.Append (valid [i]);
908 sb.Append ("' or `");
909 sb.Append (valid [count - 1]);
912 Report.Error (119, loc,
913 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb);
916 public static void UnsafeError (Location loc)
918 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
922 // Load the object from the pointer.
924 public static void LoadFromPtr (ILGenerator ig, Type t)
926 if (t == TypeManager.int32_type)
927 ig.Emit (OpCodes.Ldind_I4);
928 else if (t == TypeManager.uint32_type)
929 ig.Emit (OpCodes.Ldind_U4);
930 else if (t == TypeManager.short_type)
931 ig.Emit (OpCodes.Ldind_I2);
932 else if (t == TypeManager.ushort_type)
933 ig.Emit (OpCodes.Ldind_U2);
934 else if (t == TypeManager.char_type)
935 ig.Emit (OpCodes.Ldind_U2);
936 else if (t == TypeManager.byte_type)
937 ig.Emit (OpCodes.Ldind_U1);
938 else if (t == TypeManager.sbyte_type)
939 ig.Emit (OpCodes.Ldind_I1);
940 else if (t == TypeManager.uint64_type)
941 ig.Emit (OpCodes.Ldind_I8);
942 else if (t == TypeManager.int64_type)
943 ig.Emit (OpCodes.Ldind_I8);
944 else if (t == TypeManager.float_type)
945 ig.Emit (OpCodes.Ldind_R4);
946 else if (t == TypeManager.double_type)
947 ig.Emit (OpCodes.Ldind_R8);
948 else if (t == TypeManager.bool_type)
949 ig.Emit (OpCodes.Ldind_I1);
950 else if (t == TypeManager.intptr_type)
951 ig.Emit (OpCodes.Ldind_I);
952 else if (TypeManager.IsEnumType (t)) {
953 if (t == TypeManager.enum_type)
954 ig.Emit (OpCodes.Ldind_Ref);
956 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
957 } else if (t.IsValueType)
958 ig.Emit (OpCodes.Ldobj, t);
959 else if (t.IsPointer)
960 ig.Emit (OpCodes.Ldind_I);
962 ig.Emit (OpCodes.Ldind_Ref);
966 // The stack contains the pointer and the value of type `type'
968 public static void StoreFromPtr (ILGenerator ig, Type type)
970 if (TypeManager.IsEnumType (type))
971 type = TypeManager.EnumToUnderlying (type);
972 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
973 ig.Emit (OpCodes.Stind_I4);
974 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
975 ig.Emit (OpCodes.Stind_I8);
976 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
977 type == TypeManager.ushort_type)
978 ig.Emit (OpCodes.Stind_I2);
979 else if (type == TypeManager.float_type)
980 ig.Emit (OpCodes.Stind_R4);
981 else if (type == TypeManager.double_type)
982 ig.Emit (OpCodes.Stind_R8);
983 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
984 type == TypeManager.bool_type)
985 ig.Emit (OpCodes.Stind_I1);
986 else if (type == TypeManager.intptr_type)
987 ig.Emit (OpCodes.Stind_I);
988 else if (type.IsValueType)
989 ig.Emit (OpCodes.Stobj, type);
991 ig.Emit (OpCodes.Stind_Ref);
995 // Returns the size of type `t' if known, otherwise, 0
997 public static int GetTypeSize (Type t)
999 t = TypeManager.TypeToCoreType (t);
1000 if (t == TypeManager.int32_type ||
1001 t == TypeManager.uint32_type ||
1002 t == TypeManager.float_type)
1004 else if (t == TypeManager.int64_type ||
1005 t == TypeManager.uint64_type ||
1006 t == TypeManager.double_type)
1008 else if (t == TypeManager.byte_type ||
1009 t == TypeManager.sbyte_type ||
1010 t == TypeManager.bool_type)
1012 else if (t == TypeManager.short_type ||
1013 t == TypeManager.char_type ||
1014 t == TypeManager.ushort_type)
1016 else if (t == TypeManager.decimal_type)
1022 public static void Error_NegativeArrayIndex (Location loc)
1024 Report.Error (248, loc, "Cannot create an array with a negative size");
1027 protected void Error_CannotCallAbstractBase (string name)
1029 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1033 // Converts `source' to an int, uint, long or ulong.
1035 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1039 bool old_checked = ec.CheckState;
1040 ec.CheckState = true;
1042 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1043 if (target == null){
1044 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1045 if (target == null){
1046 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1047 if (target == null){
1048 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1050 source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1054 ec.CheckState = old_checked;
1057 // Only positive constants are allowed at compile time
1059 if (target is Constant){
1060 if (target is IntConstant){
1061 if (((IntConstant) target).Value < 0){
1062 Error_NegativeArrayIndex (loc);
1067 if (target is LongConstant){
1068 if (((LongConstant) target).Value < 0){
1069 Error_NegativeArrayIndex (loc);
1082 /// This is just a base class for expressions that can
1083 /// appear on statements (invocations, object creation,
1084 /// assignments, post/pre increment and decrement). The idea
1085 /// being that they would support an extra Emition interface that
1086 /// does not leave a result on the stack.
1088 public abstract class ExpressionStatement : Expression {
1090 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1092 Expression e = Resolve (ec);
1096 ExpressionStatement es = e as ExpressionStatement;
1098 Error (201, "Only assignment, call, increment, decrement and new object " +
1099 "expressions can be used as a statement");
1105 /// Requests the expression to be emitted in a `statement'
1106 /// context. This means that no new value is left on the
1107 /// stack after invoking this method (constrasted with
1108 /// Emit that will always leave a value on the stack).
1110 public abstract void EmitStatement (EmitContext ec);
1114 /// This kind of cast is used to encapsulate the child
1115 /// whose type is child.Type into an expression that is
1116 /// reported to return "return_type". This is used to encapsulate
1117 /// expressions which have compatible types, but need to be dealt
1118 /// at higher levels with.
1120 /// For example, a "byte" expression could be encapsulated in one
1121 /// of these as an "unsigned int". The type for the expression
1122 /// would be "unsigned int".
1125 public class EmptyCast : Expression {
1126 protected Expression child;
1128 public Expression Child {
1134 public EmptyCast (Expression child, Type return_type)
1136 eclass = child.eclass;
1137 loc = child.Location;
1142 public override Expression DoResolve (EmitContext ec)
1144 // This should never be invoked, we are born in fully
1145 // initialized state.
1150 public override void Emit (EmitContext ec)
1156 /// This is a numeric cast to a Decimal
1158 public class CastToDecimal : EmptyCast {
1160 MethodInfo conversion_operator;
1162 public CastToDecimal (Expression child)
1163 : this (child, false)
1167 public CastToDecimal (Expression child, bool find_explicit)
1168 : base (child, TypeManager.decimal_type)
1170 conversion_operator = GetConversionOperator (find_explicit);
1172 if (conversion_operator == null)
1173 throw new InternalErrorException ("Outer conversion routine is out of sync");
1176 // Returns the implicit operator that converts from
1177 // 'child.Type' to System.Decimal.
1178 MethodInfo GetConversionOperator (bool find_explicit)
1180 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1182 MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1183 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1185 foreach (MethodInfo oper in mi) {
1186 ParameterData pd = TypeManager.GetParameterData (oper);
1188 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1194 public override void Emit (EmitContext ec)
1196 ILGenerator ig = ec.ig;
1199 ig.Emit (OpCodes.Call, conversion_operator);
1204 /// This is an explicit numeric cast from a Decimal
1206 public class CastFromDecimal : EmptyCast
1208 static IDictionary operators;
1210 public CastFromDecimal (Expression child, Type return_type)
1211 : base (child, return_type)
1213 if (child.Type != TypeManager.decimal_type)
1214 throw new InternalErrorException (
1215 "The expected type is Decimal, instead it is " + child.Type.FullName);
1218 // Returns the explicit operator that converts from an
1219 // express of type System.Decimal to 'type'.
1220 public Expression Resolve ()
1222 if (operators == null) {
1223 MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1224 TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1225 BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1227 operators = new System.Collections.Specialized.HybridDictionary ();
1228 foreach (MethodInfo oper in all_oper) {
1229 ParameterData pd = TypeManager.GetParameterData (oper);
1230 if (pd.ParameterType (0) == TypeManager.decimal_type)
1231 operators.Add (oper.ReturnType, oper);
1235 return operators.Contains (type) ? this : null;
1238 public override void Emit (EmitContext ec)
1240 ILGenerator ig = ec.ig;
1243 ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1248 // We need to special case this since an empty cast of
1249 // a NullLiteral is still a Constant
1251 public class NullCast : Constant {
1252 public Constant child;
1254 public NullCast (Constant child, Type return_type):
1255 base (Location.Null)
1257 eclass = child.eclass;
1262 override public string AsString ()
1267 public override object GetValue ()
1272 public override Expression DoResolve (EmitContext ec)
1274 // This should never be invoked, we are born in fully
1275 // initialized state.
1280 public override void Emit (EmitContext ec)
1285 public override Constant Increment ()
1287 throw new NotSupportedException ();
1290 public override bool IsDefaultValue {
1292 throw new NotImplementedException ();
1296 public override bool IsNegative {
1302 public override Constant Reduce (EmitContext ec, Type target_type)
1304 throw new NotImplementedException ();
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 ());
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 ic.CheckObsoleteness (loc);
2731 if (t.IsPointer && !ec.InUnsafe) {
2736 return base.ResolveMemberAccess (ec, left, loc, original);
2739 override public Expression DoResolve (EmitContext ec)
2741 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
2742 if (FieldInfo.FieldType is TypeBuilder) {
2743 if (FieldInfo.IsStatic)
2744 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2745 GetSignatureForError ());
2747 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
2748 TypeManager.CSharpName (DeclaringType), Name);
2750 if (FieldInfo.IsStatic)
2751 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2754 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2760 if (!FieldInfo.IsStatic){
2761 if (InstanceExpression == null){
2763 // This can happen when referencing an instance field using
2764 // a fully qualified type expression: TypeName.InstanceField = xxx
2766 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
2770 // Resolve the field's instance expression while flow analysis is turned
2771 // off: when accessing a field "a.b", we must check whether the field
2772 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2773 InstanceExpression = InstanceExpression.Resolve (
2774 ec, ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis);
2775 if (InstanceExpression == null)
2779 if (!in_initializer && !ec.IsFieldInitializer) {
2780 ObsoleteAttribute oa;
2781 FieldBase f = TypeManager.GetField (FieldInfo);
2783 f.CheckObsoleteness (loc);
2785 // To be sure that type is external because we do not register generated fields
2786 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
2787 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
2789 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
2793 AnonymousContainer am = ec.CurrentAnonymousMethod;
2795 if (!FieldInfo.IsStatic){
2796 if (!am.IsIterator && (ec.TypeContainer is Struct)){
2797 Report.Error (1673, loc,
2798 "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",
2802 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
2803 ec.CaptureField (this);
2807 // If the instance expression is a local variable or parameter.
2808 IVariable var = InstanceExpression as IVariable;
2809 if ((var == null) || (var.VariableInfo == null))
2812 VariableInfo vi = var.VariableInfo;
2813 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
2816 variable_info = vi.GetSubStruct (FieldInfo.Name);
2820 void Report_AssignToReadonly (bool is_instance)
2825 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
2827 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
2829 Report.Error (is_instance ? 191 : 198, loc, msg);
2832 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2834 IVariable var = InstanceExpression as IVariable;
2835 if ((var != null) && (var.VariableInfo != null))
2836 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
2838 Expression e = DoResolve (ec);
2843 if (!FieldInfo.IsStatic && !CheckIntermediateModification ())
2846 FieldBase fb = TypeManager.GetField (FieldInfo);
2850 if (!FieldInfo.IsInitOnly)
2854 // InitOnly fields can only be assigned in constructors
2857 if (ec.IsConstructor){
2858 if (IsStatic && !ec.IsStatic)
2859 Report_AssignToReadonly (false);
2861 if (ec.ContainerType == FieldInfo.DeclaringType)
2865 Report_AssignToReadonly (!IsStatic);
2870 public override void CheckMarshallByRefAccess (Type container)
2872 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
2873 Report.SymbolRelatedToPreviousError (DeclaringType);
2874 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",
2875 GetSignatureForError ());
2879 public bool VerifyFixed ()
2881 IVariable variable = InstanceExpression as IVariable;
2882 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
2883 // We defer the InstanceExpression check after the variable check to avoid a
2884 // separate null check on InstanceExpression.
2885 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
2888 public override int GetHashCode()
2890 return FieldInfo.GetHashCode ();
2893 public override bool Equals (object obj)
2895 FieldExpr fe = obj as FieldExpr;
2899 if (FieldInfo != fe.FieldInfo)
2902 if (InstanceExpression == null || fe.InstanceExpression == null)
2905 return InstanceExpression.Equals (fe.InstanceExpression);
2908 public void Emit (EmitContext ec, bool leave_copy)
2910 ILGenerator ig = ec.ig;
2911 bool is_volatile = false;
2913 if (FieldInfo is FieldBuilder){
2914 FieldBase f = TypeManager.GetField (FieldInfo);
2916 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
2919 f.SetMemberIsUsed ();
2923 if (FieldInfo.IsStatic){
2925 ig.Emit (OpCodes.Volatile);
2927 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2930 EmitInstance (ec, false);
2933 ig.Emit (OpCodes.Volatile);
2935 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
2938 ig.Emit (OpCodes.Ldflda, FieldInfo);
2939 ig.Emit (OpCodes.Ldflda, ff.Element);
2942 ig.Emit (OpCodes.Ldfld, FieldInfo);
2947 ec.ig.Emit (OpCodes.Dup);
2948 if (!FieldInfo.IsStatic) {
2949 temp = new LocalTemporary (ec, this.Type);
2955 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
2957 FieldAttributes fa = FieldInfo.Attributes;
2958 bool is_static = (fa & FieldAttributes.Static) != 0;
2959 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
2960 ILGenerator ig = ec.ig;
2961 prepared = prepare_for_load;
2963 if (is_readonly && !ec.IsConstructor){
2964 Report_AssignToReadonly (!is_static);
2968 EmitInstance (ec, prepare_for_load);
2972 ec.ig.Emit (OpCodes.Dup);
2973 if (!FieldInfo.IsStatic) {
2974 temp = new LocalTemporary (ec, this.Type);
2979 if (FieldInfo is FieldBuilder){
2980 FieldBase f = TypeManager.GetField (FieldInfo);
2982 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
2983 ig.Emit (OpCodes.Volatile);
2990 ig.Emit (OpCodes.Stsfld, FieldInfo);
2992 ig.Emit (OpCodes.Stfld, FieldInfo);
2998 public override void Emit (EmitContext ec)
3003 public void AddressOf (EmitContext ec, AddressOp mode)
3005 ILGenerator ig = ec.ig;
3007 if (FieldInfo is FieldBuilder){
3008 FieldBase f = TypeManager.GetField (FieldInfo);
3010 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3011 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3012 f.GetSignatureForError ());
3016 if ((mode & AddressOp.Store) != 0)
3018 if ((mode & AddressOp.Load) != 0)
3019 f.SetMemberIsUsed ();
3024 // Handle initonly fields specially: make a copy and then
3025 // get the address of the copy.
3028 if (FieldInfo.IsInitOnly){
3030 if (ec.IsConstructor){
3031 if (FieldInfo.IsStatic){
3043 local = ig.DeclareLocal (type);
3044 ig.Emit (OpCodes.Stloc, local);
3045 ig.Emit (OpCodes.Ldloca, local);
3050 if (FieldInfo.IsStatic){
3051 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3053 EmitInstance (ec, false);
3054 ig.Emit (OpCodes.Ldflda, FieldInfo);
3060 // A FieldExpr whose address can not be taken
3062 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3063 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3067 public new void AddressOf (EmitContext ec, AddressOp mode)
3069 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3074 /// Expression that evaluates to a Property. The Assign class
3075 /// might set the `Value' expression if we are in an assignment.
3077 /// This is not an LValue because we need to re-write the expression, we
3078 /// can not take data from the stack and store it.
3080 public class PropertyExpr : MemberExpr, IAssignMethod {
3081 public readonly PropertyInfo PropertyInfo;
3084 // This is set externally by the `BaseAccess' class
3087 MethodInfo getter, setter;
3092 LocalTemporary temp;
3095 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3097 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
3100 eclass = ExprClass.PropertyAccess;
3104 type = TypeManager.TypeToCoreType (pi.PropertyType);
3106 ResolveAccessors (ec);
3109 public override string Name {
3111 return PropertyInfo.Name;
3115 public override bool IsInstance {
3121 public override bool IsStatic {
3127 public override Type DeclaringType {
3129 return PropertyInfo.DeclaringType;
3133 public override string GetSignatureForError ()
3135 return TypeManager.GetFullNameSignature (PropertyInfo);
3138 void FindAccessors (Type invocation_type)
3140 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3141 BindingFlags.Static | BindingFlags.Instance |
3142 BindingFlags.DeclaredOnly;
3144 Type current = PropertyInfo.DeclaringType;
3145 for (; current != null; current = current.BaseType) {
3146 MemberInfo[] group = TypeManager.MemberLookup (
3147 invocation_type, invocation_type, current,
3148 MemberTypes.Property, flags, PropertyInfo.Name, null);
3153 if (group.Length != 1)
3154 // Oooops, can this ever happen ?
3157 PropertyInfo pi = (PropertyInfo) group [0];
3160 getter = pi.GetGetMethod (true);
3163 setter = pi.GetSetMethod (true);
3165 MethodInfo accessor = getter != null ? getter : setter;
3167 if (!accessor.IsVirtual)
3173 // We also perform the permission checking here, as the PropertyInfo does not
3174 // hold the information for the accessibility of its setter/getter
3176 void ResolveAccessors (EmitContext ec)
3178 FindAccessors (ec.ContainerType);
3180 if (getter != null) {
3181 IMethodData md = TypeManager.GetMethod (getter);
3183 md.SetMemberIsUsed ();
3185 AccessorTable [getter] = PropertyInfo;
3186 is_static = getter.IsStatic;
3189 if (setter != null) {
3190 IMethodData md = TypeManager.GetMethod (setter);
3192 md.SetMemberIsUsed ();
3194 AccessorTable [setter] = PropertyInfo;
3195 is_static = setter.IsStatic;
3199 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3202 InstanceExpression = null;
3206 if (InstanceExpression == null) {
3207 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3211 InstanceExpression = InstanceExpression.DoResolve (ec);
3212 if (InstanceExpression == null)
3215 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3217 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) {
3218 if ((InstanceExpression.Type != ec.ContainerType) &&
3219 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3220 Report.Error (1540, loc, "Cannot access protected member `" +
3221 PropertyInfo.DeclaringType + "." + PropertyInfo.Name +
3222 "' via a qualifier of type `" +
3223 TypeManager.CSharpName (InstanceExpression.Type) +
3224 "'; the qualifier must be of type `" +
3225 TypeManager.CSharpName (ec.ContainerType) +
3226 "' (or derived from it)");
3234 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3236 // TODO: correctly we should compare arguments but it will lead to bigger changes
3237 if (mi is MethodBuilder) {
3238 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3242 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3244 ParameterData iparams = TypeManager.GetParameterData (mi);
3245 sig.Append (getter ? "get_" : "set_");
3247 sig.Append (iparams.GetSignatureForError ());
3249 Report.SymbolRelatedToPreviousError (mi);
3250 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3251 Name, sig.ToString ());
3254 override public Expression DoResolve (EmitContext ec)
3259 if (getter != null){
3260 if (TypeManager.GetArgumentTypes (getter).Length != 0){
3261 Error_PropertyNotFound (getter, true);
3266 if (getter == null){
3268 // The following condition happens if the PropertyExpr was
3269 // created, but is invalid (ie, the property is inaccessible),
3270 // and we did not want to embed the knowledge about this in
3271 // the caller routine. This only avoids double error reporting.
3276 if (InstanceExpression != EmptyExpression.Null) {
3277 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3278 TypeManager.GetFullNameSignature (PropertyInfo));
3283 bool must_do_cs1540_check = false;
3284 if (getter != null &&
3285 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3286 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3287 if (pm != null && pm.HasCustomAccessModifier) {
3288 Report.SymbolRelatedToPreviousError (pm);
3289 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3290 TypeManager.CSharpSignature (getter));
3293 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3297 if (!InstanceResolve (ec, must_do_cs1540_check))
3301 // Only base will allow this invocation to happen.
3303 if (IsBase && getter.IsAbstract) {
3304 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3308 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3318 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3320 if (setter == null){
3322 // The following condition happens if the PropertyExpr was
3323 // created, but is invalid (ie, the property is inaccessible),
3324 // and we did not want to embed the knowledge about this in
3325 // the caller routine. This only avoids double error reporting.
3330 Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)",
3331 TypeManager.GetFullNameSignature (PropertyInfo));
3335 if (TypeManager.GetArgumentTypes (setter).Length != 1){
3336 Error_PropertyNotFound (setter, false);
3340 bool must_do_cs1540_check;
3341 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3342 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3343 if (pm != null && pm.HasCustomAccessModifier) {
3344 Report.SymbolRelatedToPreviousError (pm);
3345 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3346 TypeManager.CSharpSignature (setter));
3349 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3353 if (!InstanceResolve (ec, must_do_cs1540_check))
3357 // Only base will allow this invocation to happen.
3359 if (IsBase && setter.IsAbstract){
3360 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3365 // Check that we are not making changes to a temporary memory location
3367 if (InstanceExpression != null && !CheckIntermediateModification ())
3373 public override void Emit (EmitContext ec)
3378 public void Emit (EmitContext ec, bool leave_copy)
3381 // Special case: length of single dimension array property is turned into ldlen
3383 if ((getter == TypeManager.system_int_array_get_length) ||
3384 (getter == TypeManager.int_array_get_length)){
3385 Type iet = InstanceExpression.Type;
3388 // System.Array.Length can be called, but the Type does not
3389 // support invoking GetArrayRank, so test for that case first
3391 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3393 EmitInstance (ec, false);
3394 ec.ig.Emit (OpCodes.Ldlen);
3395 ec.ig.Emit (OpCodes.Conv_I4);
3400 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3403 ec.ig.Emit (OpCodes.Dup);
3405 temp = new LocalTemporary (ec, this.Type);
3412 // Implements the IAssignMethod interface for assignments
3414 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3416 Expression my_source = source;
3418 prepared = prepare_for_load;
3423 ec.ig.Emit (OpCodes.Dup);
3425 temp = new LocalTemporary (ec, this.Type);
3429 } else if (leave_copy) {
3432 temp = new LocalTemporary (ec, this.Type);
3438 ArrayList args = new ArrayList (1);
3439 args.Add (new Argument (my_source, Argument.AType.Expression));
3441 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3449 /// Fully resolved expression that evaluates to an Event
3451 public class EventExpr : MemberExpr {
3452 public readonly EventInfo EventInfo;
3455 MethodInfo add_accessor, remove_accessor;
3457 public EventExpr (EventInfo ei, Location loc)
3461 eclass = ExprClass.EventAccess;
3463 add_accessor = TypeManager.GetAddMethod (ei);
3464 remove_accessor = TypeManager.GetRemoveMethod (ei);
3466 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3469 if (EventInfo is MyEventBuilder){
3470 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3471 type = eb.EventType;
3474 type = EventInfo.EventHandlerType;
3477 public override string Name {
3479 return EventInfo.Name;
3483 public override bool IsInstance {
3489 public override bool IsStatic {
3495 public override Type DeclaringType {
3497 return EventInfo.DeclaringType;
3501 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3502 SimpleName original)
3505 // If the event is local to this class, we transform ourselves into a FieldExpr
3508 if (EventInfo.DeclaringType == ec.ContainerType ||
3509 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3510 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3513 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc);
3516 Report.Error (-200, loc, "Internal error!!");
3520 InstanceExpression = null;
3522 return ml.ResolveMemberAccess (ec, left, loc, original);
3526 return base.ResolveMemberAccess (ec, left, loc, original);
3530 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3533 InstanceExpression = null;
3537 if (InstanceExpression == null) {
3538 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3542 InstanceExpression = InstanceExpression.DoResolve (ec);
3543 if (InstanceExpression == null)
3547 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3548 // However, in the Event case, we reported a CS0122 instead.
3550 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) {
3551 if ((InstanceExpression.Type != ec.ContainerType) &&
3552 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3553 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3561 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3563 return DoResolve (ec);
3566 public override Expression DoResolve (EmitContext ec)
3568 bool must_do_cs1540_check;
3569 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3570 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3571 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3575 if (!InstanceResolve (ec, must_do_cs1540_check))
3581 public override void Emit (EmitContext ec)
3583 if (InstanceExpression is This)
3584 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3586 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3587 "(except on the defining type)", Name);
3590 public override string GetSignatureForError ()
3592 return TypeManager.CSharpSignature (EventInfo);
3595 public void EmitAddOrRemove (EmitContext ec, Expression source)
3597 BinaryDelegate source_del = (BinaryDelegate) source;
3598 Expression handler = source_del.Right;
3600 Argument arg = new Argument (handler, Argument.AType.Expression);
3601 ArrayList args = new ArrayList ();
3605 if (source_del.IsAddition)
3606 Invocation.EmitCall (
3607 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3609 Invocation.EmitCall (
3610 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3615 public class TemporaryVariable : Expression, IMemoryLocation
3619 public TemporaryVariable (Type type, Location loc)
3623 eclass = ExprClass.Value;
3626 public override Expression DoResolve (EmitContext ec)
3631 TypeExpr te = new TypeExpression (type, loc);
3632 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3633 if (!li.Resolve (ec))
3636 AnonymousContainer am = ec.CurrentAnonymousMethod;
3637 if ((am != null) && am.IsIterator)
3638 ec.CaptureVariable (li);
3643 public override void Emit (EmitContext ec)
3645 ILGenerator ig = ec.ig;
3647 if (li.FieldBuilder != null) {
3648 ig.Emit (OpCodes.Ldarg_0);
3649 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3651 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3655 public void EmitLoadAddress (EmitContext ec)
3657 ILGenerator ig = ec.ig;
3659 if (li.FieldBuilder != null) {
3660 ig.Emit (OpCodes.Ldarg_0);
3661 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3663 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3667 public void Store (EmitContext ec, Expression right_side)
3669 if (li.FieldBuilder != null)
3670 ec.ig.Emit (OpCodes.Ldarg_0);
3672 right_side.Emit (ec);
3673 if (li.FieldBuilder != null) {
3674 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3676 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3680 public void EmitThis (EmitContext ec)
3682 if (li.FieldBuilder != null) {
3683 ec.ig.Emit (OpCodes.Ldarg_0);
3687 public void EmitStore (ILGenerator ig)
3689 if (li.FieldBuilder != null)
3690 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3692 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3695 public void AddressOf (EmitContext ec, AddressOp mode)
3697 EmitLoadAddress (ec);