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, String.Format ("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 {
1289 throw new NotImplementedException ();
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 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 InstanceExpression.Type != ec.ContainerType &&
3219 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3220 InstanceExpression.Type.IsSubclassOf (PropertyInfo.DeclaringType)) {
3221 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3228 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3230 // TODO: correctly we should compare arguments but it will lead to bigger changes
3231 if (mi is MethodBuilder) {
3232 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3236 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3238 ParameterData iparams = TypeManager.GetParameterData (mi);
3239 sig.Append (getter ? "get_" : "set_");
3241 sig.Append (iparams.GetSignatureForError ());
3243 Report.SymbolRelatedToPreviousError (mi);
3244 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3245 Name, sig.ToString ());
3248 override public Expression DoResolve (EmitContext ec)
3253 if (getter != null){
3254 if (TypeManager.GetParameterData (getter).Count != 0){
3255 Error_PropertyNotFound (getter, true);
3260 if (getter == null){
3262 // The following condition happens if the PropertyExpr was
3263 // created, but is invalid (ie, the property is inaccessible),
3264 // and we did not want to embed the knowledge about this in
3265 // the caller routine. This only avoids double error reporting.
3270 if (InstanceExpression != EmptyExpression.Null) {
3271 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3272 TypeManager.GetFullNameSignature (PropertyInfo));
3277 bool must_do_cs1540_check = false;
3278 if (getter != null &&
3279 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3280 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3281 if (pm != null && pm.HasCustomAccessModifier) {
3282 Report.SymbolRelatedToPreviousError (pm);
3283 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3284 TypeManager.CSharpSignature (getter));
3287 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3291 if (!InstanceResolve (ec, must_do_cs1540_check))
3295 // Only base will allow this invocation to happen.
3297 if (IsBase && getter.IsAbstract) {
3298 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3302 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3312 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3314 if (setter == null){
3316 // The following condition happens if the PropertyExpr was
3317 // created, but is invalid (ie, the property is inaccessible),
3318 // and we did not want to embed the knowledge about this in
3319 // the caller routine. This only avoids double error reporting.
3324 Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)",
3325 TypeManager.GetFullNameSignature (PropertyInfo));
3329 if (TypeManager.GetParameterData (setter).Count != 1){
3330 Error_PropertyNotFound (setter, false);
3334 bool must_do_cs1540_check;
3335 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3336 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3337 if (pm != null && pm.HasCustomAccessModifier) {
3338 Report.SymbolRelatedToPreviousError (pm);
3339 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3340 TypeManager.CSharpSignature (setter));
3343 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3347 if (!InstanceResolve (ec, must_do_cs1540_check))
3351 // Only base will allow this invocation to happen.
3353 if (IsBase && setter.IsAbstract){
3354 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3359 // Check that we are not making changes to a temporary memory location
3361 if (InstanceExpression != null && !CheckIntermediateModification ())
3367 public override void Emit (EmitContext ec)
3372 public void Emit (EmitContext ec, bool leave_copy)
3375 // Special case: length of single dimension array property is turned into ldlen
3377 if ((getter == TypeManager.system_int_array_get_length) ||
3378 (getter == TypeManager.int_array_get_length)){
3379 Type iet = InstanceExpression.Type;
3382 // System.Array.Length can be called, but the Type does not
3383 // support invoking GetArrayRank, so test for that case first
3385 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3387 EmitInstance (ec, false);
3388 ec.ig.Emit (OpCodes.Ldlen);
3389 ec.ig.Emit (OpCodes.Conv_I4);
3394 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3397 ec.ig.Emit (OpCodes.Dup);
3399 temp = new LocalTemporary (ec, this.Type);
3406 // Implements the IAssignMethod interface for assignments
3408 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3410 Expression my_source = source;
3412 prepared = prepare_for_load;
3417 ec.ig.Emit (OpCodes.Dup);
3419 temp = new LocalTemporary (ec, this.Type);
3423 } else if (leave_copy) {
3426 temp = new LocalTemporary (ec, this.Type);
3432 ArrayList args = new ArrayList (1);
3433 args.Add (new Argument (my_source, Argument.AType.Expression));
3435 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3443 /// Fully resolved expression that evaluates to an Event
3445 public class EventExpr : MemberExpr {
3446 public readonly EventInfo EventInfo;
3449 MethodInfo add_accessor, remove_accessor;
3451 public EventExpr (EventInfo ei, Location loc)
3455 eclass = ExprClass.EventAccess;
3457 add_accessor = TypeManager.GetAddMethod (ei);
3458 remove_accessor = TypeManager.GetRemoveMethod (ei);
3460 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3463 if (EventInfo is MyEventBuilder){
3464 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3465 type = eb.EventType;
3468 type = EventInfo.EventHandlerType;
3471 public override string Name {
3473 return EventInfo.Name;
3477 public override bool IsInstance {
3483 public override bool IsStatic {
3489 public override Type DeclaringType {
3491 return EventInfo.DeclaringType;
3495 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3496 SimpleName original)
3499 // If the event is local to this class, we transform ourselves into a FieldExpr
3502 if (EventInfo.DeclaringType == ec.ContainerType ||
3503 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3504 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3507 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc);
3510 Report.Error (-200, loc, "Internal error!!");
3514 InstanceExpression = null;
3516 return ml.ResolveMemberAccess (ec, left, loc, original);
3520 return base.ResolveMemberAccess (ec, left, loc, original);
3524 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3527 InstanceExpression = null;
3531 if (InstanceExpression == null) {
3532 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3536 InstanceExpression = InstanceExpression.DoResolve (ec);
3537 if (InstanceExpression == null)
3541 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3542 // However, in the Event case, we reported a CS0122 instead.
3544 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) {
3545 if ((InstanceExpression.Type != ec.ContainerType) &&
3546 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3547 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3555 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3557 return DoResolve (ec);
3560 public override Expression DoResolve (EmitContext ec)
3562 bool must_do_cs1540_check;
3563 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3564 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3565 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3569 if (!InstanceResolve (ec, must_do_cs1540_check))
3575 public override void Emit (EmitContext ec)
3577 if (InstanceExpression is This)
3578 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3580 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3581 "(except on the defining type)", Name);
3584 public override string GetSignatureForError ()
3586 return TypeManager.CSharpSignature (EventInfo);
3589 public void EmitAddOrRemove (EmitContext ec, Expression source)
3591 BinaryDelegate source_del = (BinaryDelegate) source;
3592 Expression handler = source_del.Right;
3594 Argument arg = new Argument (handler, Argument.AType.Expression);
3595 ArrayList args = new ArrayList ();
3599 if (source_del.IsAddition)
3600 Invocation.EmitCall (
3601 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3603 Invocation.EmitCall (
3604 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3609 public class TemporaryVariable : Expression, IMemoryLocation
3613 public TemporaryVariable (Type type, Location loc)
3617 eclass = ExprClass.Value;
3620 public override Expression DoResolve (EmitContext ec)
3625 TypeExpr te = new TypeExpression (type, loc);
3626 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3627 if (!li.Resolve (ec))
3630 AnonymousContainer am = ec.CurrentAnonymousMethod;
3631 if ((am != null) && am.IsIterator)
3632 ec.CaptureVariable (li);
3637 public override void Emit (EmitContext ec)
3639 ILGenerator ig = ec.ig;
3641 if (li.FieldBuilder != null) {
3642 ig.Emit (OpCodes.Ldarg_0);
3643 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3645 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3649 public void EmitLoadAddress (EmitContext ec)
3651 ILGenerator ig = ec.ig;
3653 if (li.FieldBuilder != null) {
3654 ig.Emit (OpCodes.Ldarg_0);
3655 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3657 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3661 public void Store (EmitContext ec, Expression right_side)
3663 if (li.FieldBuilder != null)
3664 ec.ig.Emit (OpCodes.Ldarg_0);
3666 right_side.Emit (ec);
3667 if (li.FieldBuilder != null) {
3668 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3670 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3674 public void EmitThis (EmitContext ec)
3676 if (li.FieldBuilder != null) {
3677 ec.ig.Emit (OpCodes.Ldarg_0);
3681 public void EmitStore (ILGenerator ig)
3683 if (li.FieldBuilder != null)
3684 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3686 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3689 public void AddressOf (EmitContext ec, AddressOp mode)
3691 EmitLoadAddress (ec);