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 bool GetAttributableValue (Type valueType, out object value)
142 Attribute.Error_AttributeArgumentNotValid (loc);
147 public virtual string GetSignatureForError ()
149 return TypeManager.CSharpName (type);
152 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
154 MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
156 must_do_cs1540_check = false; // by default we do not check for this
159 // If only accessible to the current class or children
161 if (ma == MethodAttributes.Private)
162 return invocation_type == mi.DeclaringType ||
163 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
165 if (mi.DeclaringType.Assembly == invocation_type.Assembly) {
166 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
169 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
173 // Family and FamANDAssem require that we derive.
174 // FamORAssem requires that we derive if in different assemblies.
175 if (ma == MethodAttributes.Family ||
176 ma == MethodAttributes.FamANDAssem ||
177 ma == MethodAttributes.FamORAssem) {
178 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
181 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
182 must_do_cs1540_check = true;
191 /// Performs semantic analysis on the Expression
195 /// The Resolve method is invoked to perform the semantic analysis
198 /// The return value is an expression (it can be the
199 /// same expression in some cases) or a new
200 /// expression that better represents this node.
202 /// For example, optimizations of Unary (LiteralInt)
203 /// would return a new LiteralInt with a negated
206 /// If there is an error during semantic analysis,
207 /// then an error should be reported (using Report)
208 /// and a null value should be returned.
210 /// There are two side effects expected from calling
211 /// Resolve(): the the field variable "eclass" should
212 /// be set to any value of the enumeration
213 /// `ExprClass' and the type variable should be set
214 /// to a valid type (this is the type of the
217 public abstract Expression DoResolve (EmitContext ec);
219 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
225 // This is used if the expression should be resolved as a type or namespace name.
226 // the default implementation fails.
228 public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
234 // This is used to resolve the expression as a type, a null
235 // value will be returned if the expression is not a type
238 public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
240 TypeExpr te = ResolveAsBaseTerminal (ec, silent);
244 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
245 if (obsolete_attr != null && !ec.IsInObsoleteScope) {
246 AttributeTester.Report_ObsoleteMessage (obsolete_attr, GetSignatureForError (), Location);
251 public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent)
253 int errors = Report.Errors;
255 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
258 if (!silent && errors == Report.Errors)
259 Report.Error (118, loc, "Expecting a type.");
263 if (fne.eclass != ExprClass.Type) {
264 if (!silent && errors == Report.Errors)
265 fne.Error_UnexpectedKind (null, "type", loc);
269 TypeExpr te = fne as TypeExpr;
271 if (!te.CheckAccessLevel (ec.DeclContainer)) {
272 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
280 public static void ErrorIsInaccesible (Location loc, string name)
282 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
285 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
287 Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
288 + " the qualifier must be of type `{2}' (or derived from it)",
289 TypeManager.GetFullNameSignature (m),
290 TypeManager.CSharpName (qualifier),
291 TypeManager.CSharpName (container));
295 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
297 if (Type.Name == target.Name){
298 Report.ExtraInformation (loc,
300 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
301 Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
306 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
307 GetSignatureForError (), TypeManager.CSharpName (target));
311 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
312 bool b = Convert.ExplicitNumericConversion (e, target) != null;
314 if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
315 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
316 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
320 if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
321 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
322 GetSignatureForError (), TypeManager.CSharpName (target));
326 Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
327 Type == TypeManager.anonymous_method_type ?
328 "anonymous method" : "`" + GetSignatureForError () + "'",
329 TypeManager.CSharpName (target));
332 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
334 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
335 TypeManager.CSharpName (type), name);
338 ResolveFlags ExprClassToResolveFlags
343 case ExprClass.Namespace:
344 return ResolveFlags.Type;
346 case ExprClass.MethodGroup:
347 return ResolveFlags.MethodGroup;
349 case ExprClass.Value:
350 case ExprClass.Variable:
351 case ExprClass.PropertyAccess:
352 case ExprClass.EventAccess:
353 case ExprClass.IndexerAccess:
354 return ResolveFlags.VariableOrValue;
357 throw new Exception ("Expression " + GetType () +
358 " ExprClass is Invalid after resolve");
364 /// Resolves an expression and performs semantic analysis on it.
368 /// Currently Resolve wraps DoResolve to perform sanity
369 /// checking and assertion checking on what we expect from Resolve.
371 public Expression Resolve (EmitContext ec, ResolveFlags flags)
373 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
374 return ResolveAsTypeStep (ec, false);
376 bool old_do_flow_analysis = ec.DoFlowAnalysis;
377 bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;
378 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
379 ec.DoFlowAnalysis = false;
380 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
381 ec.OmitStructFlowAnalysis = true;
384 if (this is SimpleName) {
385 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
386 e = ((SimpleName) this).DoResolve (ec, intermediate);
391 ec.DoFlowAnalysis = old_do_flow_analysis;
392 ec.OmitStructFlowAnalysis = old_omit_struct_analysis;
397 if ((flags & e.ExprClassToResolveFlags) == 0) {
398 e.Error_UnexpectedKind (flags, loc);
402 if (e.type == null && !(e is Namespace)) {
403 throw new Exception (
404 "Expression " + e.GetType () +
405 " did not set its type after Resolve\n" +
406 "called from: " + this.GetType ());
413 /// Resolves an expression and performs semantic analysis on it.
415 public Expression Resolve (EmitContext ec)
417 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
419 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
420 ((MethodGroupExpr) e).ReportUsageError ();
426 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
428 Expression e = Resolve (ec);
432 Constant c = e as Constant;
436 EmptyCast empty = e as EmptyCast;
438 c = empty.Child as Constant;
440 // TODO: not sure about this maybe there is easier way how to use EmptyCast
447 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
452 /// Resolves an expression for LValue assignment
456 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
457 /// checking and assertion checking on what we expect from Resolve
459 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
461 int errors = Report.Errors;
462 Expression e = DoResolveLValue (ec, right_side);
465 if (errors == Report.Errors)
466 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
471 if (e.eclass == ExprClass.Invalid)
472 throw new Exception ("Expression " + e +
473 " ExprClass is Invalid after resolve");
475 if (e.eclass == ExprClass.MethodGroup) {
476 ((MethodGroupExpr) e).ReportUsageError ();
481 throw new Exception ("Expression " + e +
482 " did not set its type after Resolve");
489 /// Emits the code for the expression
493 /// The Emit method is invoked to generate the code
494 /// for the expression.
496 public abstract void Emit (EmitContext ec);
498 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
501 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
505 /// Protected constructor. Only derivate types should
506 /// be able to be created
509 protected Expression ()
511 eclass = ExprClass.Invalid;
516 /// Returns a literalized version of a literal FieldInfo
520 /// The possible return values are:
521 /// IntConstant, UIntConstant
522 /// LongLiteral, ULongConstant
523 /// FloatConstant, DoubleConstant
526 /// The value returned is already resolved.
528 public static Constant Constantify (object v, Type t)
530 if (t == TypeManager.int32_type)
531 return new IntConstant ((int) v, Location.Null);
532 else if (t == TypeManager.uint32_type)
533 return new UIntConstant ((uint) v, Location.Null);
534 else if (t == TypeManager.int64_type)
535 return new LongConstant ((long) v, Location.Null);
536 else if (t == TypeManager.uint64_type)
537 return new ULongConstant ((ulong) v, Location.Null);
538 else if (t == TypeManager.float_type)
539 return new FloatConstant ((float) v, Location.Null);
540 else if (t == TypeManager.double_type)
541 return new DoubleConstant ((double) v, Location.Null);
542 else if (t == TypeManager.string_type)
543 return new StringConstant ((string) v, Location.Null);
544 else if (t == TypeManager.short_type)
545 return new ShortConstant ((short)v, Location.Null);
546 else if (t == TypeManager.ushort_type)
547 return new UShortConstant ((ushort)v, Location.Null);
548 else if (t == TypeManager.sbyte_type)
549 return new SByteConstant ((sbyte)v, Location.Null);
550 else if (t == TypeManager.byte_type)
551 return new ByteConstant ((byte)v, Location.Null);
552 else if (t == TypeManager.char_type)
553 return new CharConstant ((char)v, Location.Null);
554 else if (t == TypeManager.bool_type)
555 return new BoolConstant ((bool) v, Location.Null);
556 else if (t == TypeManager.decimal_type)
557 return new DecimalConstant ((decimal) v, Location.Null);
558 else if (TypeManager.IsEnumType (t)){
559 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
561 real_type = System.Enum.GetUnderlyingType (real_type);
563 Constant e = Constantify (v, real_type);
565 return new EnumConstant (e, t);
566 } else if (v == null && !TypeManager.IsValueType (t))
567 return new NullLiteral (Location.Null);
569 throw new Exception ("Unknown type for constant (" + t +
574 /// Returns a fully formed expression after a MemberLookup
577 public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
580 return new EventExpr ((EventInfo) mi, loc);
581 else if (mi is FieldInfo)
582 return new FieldExpr ((FieldInfo) mi, loc);
583 else if (mi is PropertyInfo)
584 return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
585 else if (mi is Type){
586 return new TypeExpression ((System.Type) mi, loc);
592 protected static ArrayList almostMatchedMembers = new ArrayList (4);
595 // FIXME: Probably implement a cache for (t,name,current_access_set)?
597 // This code could use some optimizations, but we need to do some
598 // measurements. For example, we could use a delegate to `flag' when
599 // something can not any longer be a method-group (because it is something
603 // If the return value is an Array, then it is an array of
606 // If the return value is an MemberInfo, it is anything, but a Method
610 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
611 // the arguments here and have MemberLookup return only the methods that
612 // match the argument count/type, unlike we are doing now (we delay this
615 // This is so we can catch correctly attempts to invoke instance methods
616 // from a static body (scan for error 120 in ResolveSimpleName).
619 // FIXME: Potential optimization, have a static ArrayList
622 public static Expression MemberLookup (Type container_type, Type queried_type, string name,
623 MemberTypes mt, BindingFlags bf, Location loc)
625 return MemberLookup (container_type, null, queried_type, name, mt, bf, loc);
629 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
630 // `qualifier_type' or null to lookup members in the current class.
633 public static Expression MemberLookup (Type container_type,
634 Type qualifier_type, Type queried_type,
635 string name, MemberTypes mt,
636 BindingFlags bf, Location loc)
638 almostMatchedMembers.Clear ();
640 MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
641 queried_type, mt, bf, name, almostMatchedMembers);
646 int count = mi.Length;
648 if (mi [0] is MethodBase)
649 return new MethodGroupExpr (mi, loc);
654 return ExprClassFromMemberInfo (container_type, mi [0], loc);
657 public const MemberTypes AllMemberTypes =
658 MemberTypes.Constructor |
662 MemberTypes.NestedType |
663 MemberTypes.Property;
665 public const BindingFlags AllBindingFlags =
666 BindingFlags.Public |
667 BindingFlags.Static |
668 BindingFlags.Instance;
670 public static Expression MemberLookup (Type container_type, Type queried_type,
671 string name, Location loc)
673 return MemberLookup (container_type, null, queried_type, name,
674 AllMemberTypes, AllBindingFlags, loc);
677 public static Expression MemberLookup (Type container_type, Type qualifier_type,
678 Type queried_type, string name, Location loc)
680 return MemberLookup (container_type, qualifier_type, queried_type,
681 name, AllMemberTypes, AllBindingFlags, loc);
684 public static Expression MethodLookup (EmitContext ec, Type queried_type,
685 string name, Location loc)
687 return MemberLookup (ec.ContainerType, null, queried_type, name,
688 MemberTypes.Method, AllBindingFlags, loc);
692 /// This is a wrapper for MemberLookup that is not used to "probe", but
693 /// to find a final definition. If the final definition is not found, we
694 /// look for private members and display a useful debugging message if we
697 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
698 Type queried_type, string name, Location loc)
700 return MemberLookupFinal (ec, qualifier_type, queried_type, name,
701 AllMemberTypes, AllBindingFlags, loc);
704 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
705 Type queried_type, string name,
706 MemberTypes mt, BindingFlags bf,
711 int errors = Report.Errors;
713 e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
715 if (e == null && errors == Report.Errors)
716 // No errors were reported by MemberLookup, but there was an error.
717 MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
722 public static void MemberLookupFailed (Type container_type, Type qualifier_type,
723 Type queried_type, string name,
724 string class_name, bool complain_if_none_found,
727 if (almostMatchedMembers.Count != 0) {
728 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
729 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
730 for (int j = 0; j < i; ++j) {
731 if (m == almostMatchedMembers [j]) {
739 Type declaring_type = m.DeclaringType;
741 Report.SymbolRelatedToPreviousError (m);
742 if (qualifier_type == null) {
743 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
744 TypeManager.CSharpName (m.DeclaringType),
745 TypeManager.CSharpName (container_type));
747 } else if (qualifier_type != container_type &&
748 TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) {
749 // Although a derived class can access protected members of
750 // its base class it cannot do so through an instance of the
751 // base class (CS1540). If the qualifier_type is a base of the
752 // ec.ContainerType and the lookup succeeds with the latter one,
753 // then we are in this situation.
754 Error_CannotAccessProtected (loc, m, qualifier_type, container_type);
756 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
759 almostMatchedMembers.Clear ();
763 MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
764 AllMemberTypes, AllBindingFlags |
765 BindingFlags.NonPublic, name, null);
767 if (lookup == null) {
768 if (!complain_if_none_found)
771 if (class_name != null)
772 Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
775 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
779 MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
780 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
781 if (name == ".ctor" && ml.Count == 0)
783 Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
787 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
791 /// Returns an expression that can be used to invoke operator true
792 /// on the expression if it exists.
794 static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
796 return GetOperatorTrueOrFalse (ec, e, true, loc);
800 /// Returns an expression that can be used to invoke operator false
801 /// on the expression if it exists.
803 static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
805 return GetOperatorTrueOrFalse (ec, e, false, loc);
808 static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
811 Expression operator_group;
813 operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
814 if (operator_group == null)
817 ArrayList arguments = new ArrayList ();
818 arguments.Add (new Argument (e, Argument.AType.Expression));
819 method = Invocation.OverloadResolve (
820 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
825 return new StaticCallExpr ((MethodInfo) method, arguments, loc);
829 /// Resolves the expression `e' into a boolean expression: either through
830 /// an implicit conversion, or through an `operator true' invocation
832 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
838 if (e.Type == TypeManager.bool_type)
841 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
843 if (converted != null)
847 // If no implicit conversion to bool exists, try using `operator true'
849 converted = Expression.GetOperatorTrue (ec, e, loc);
850 if (converted == null){
851 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
857 public virtual string ExprClassName
861 case ExprClass.Invalid:
863 case ExprClass.Value:
865 case ExprClass.Variable:
867 case ExprClass.Namespace:
871 case ExprClass.MethodGroup:
872 return "method group";
873 case ExprClass.PropertyAccess:
874 return "property access";
875 case ExprClass.EventAccess:
876 return "event access";
877 case ExprClass.IndexerAccess:
878 return "indexer access";
879 case ExprClass.Nothing:
882 throw new Exception ("Should not happen");
887 /// Reports that we were expecting `expr' to be of class `expected'
889 public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
891 Error_UnexpectedKind (ds, expected, ExprClassName, loc);
894 public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
896 string name = GetSignatureForError ();
898 name = ds.GetSignatureForError () + '.' + name;
900 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
901 name, was, expected);
904 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
906 string [] valid = new string [4];
909 if ((flags & ResolveFlags.VariableOrValue) != 0) {
910 valid [count++] = "variable";
911 valid [count++] = "value";
914 if ((flags & ResolveFlags.Type) != 0)
915 valid [count++] = "type";
917 if ((flags & ResolveFlags.MethodGroup) != 0)
918 valid [count++] = "method group";
921 valid [count++] = "unknown";
923 StringBuilder sb = new StringBuilder (valid [0]);
924 for (int i = 1; i < count - 1; i++) {
926 sb.Append (valid [i]);
929 sb.Append ("' or `");
930 sb.Append (valid [count - 1]);
933 Report.Error (119, loc,
934 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
937 public static void UnsafeError (Location loc)
939 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
943 // Load the object from the pointer.
945 public static void LoadFromPtr (ILGenerator ig, Type t)
947 if (t == TypeManager.int32_type)
948 ig.Emit (OpCodes.Ldind_I4);
949 else if (t == TypeManager.uint32_type)
950 ig.Emit (OpCodes.Ldind_U4);
951 else if (t == TypeManager.short_type)
952 ig.Emit (OpCodes.Ldind_I2);
953 else if (t == TypeManager.ushort_type)
954 ig.Emit (OpCodes.Ldind_U2);
955 else if (t == TypeManager.char_type)
956 ig.Emit (OpCodes.Ldind_U2);
957 else if (t == TypeManager.byte_type)
958 ig.Emit (OpCodes.Ldind_U1);
959 else if (t == TypeManager.sbyte_type)
960 ig.Emit (OpCodes.Ldind_I1);
961 else if (t == TypeManager.uint64_type)
962 ig.Emit (OpCodes.Ldind_I8);
963 else if (t == TypeManager.int64_type)
964 ig.Emit (OpCodes.Ldind_I8);
965 else if (t == TypeManager.float_type)
966 ig.Emit (OpCodes.Ldind_R4);
967 else if (t == TypeManager.double_type)
968 ig.Emit (OpCodes.Ldind_R8);
969 else if (t == TypeManager.bool_type)
970 ig.Emit (OpCodes.Ldind_I1);
971 else if (t == TypeManager.intptr_type)
972 ig.Emit (OpCodes.Ldind_I);
973 else if (TypeManager.IsEnumType (t)) {
974 if (t == TypeManager.enum_type)
975 ig.Emit (OpCodes.Ldind_Ref);
977 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
978 } else if (t.IsValueType)
979 ig.Emit (OpCodes.Ldobj, t);
980 else if (t.IsPointer)
981 ig.Emit (OpCodes.Ldind_I);
983 ig.Emit (OpCodes.Ldind_Ref);
987 // The stack contains the pointer and the value of type `type'
989 public static void StoreFromPtr (ILGenerator ig, Type type)
991 if (TypeManager.IsEnumType (type))
992 type = TypeManager.EnumToUnderlying (type);
993 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
994 ig.Emit (OpCodes.Stind_I4);
995 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
996 ig.Emit (OpCodes.Stind_I8);
997 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
998 type == TypeManager.ushort_type)
999 ig.Emit (OpCodes.Stind_I2);
1000 else if (type == TypeManager.float_type)
1001 ig.Emit (OpCodes.Stind_R4);
1002 else if (type == TypeManager.double_type)
1003 ig.Emit (OpCodes.Stind_R8);
1004 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1005 type == TypeManager.bool_type)
1006 ig.Emit (OpCodes.Stind_I1);
1007 else if (type == TypeManager.intptr_type)
1008 ig.Emit (OpCodes.Stind_I);
1009 else if (type.IsValueType)
1010 ig.Emit (OpCodes.Stobj, type);
1012 ig.Emit (OpCodes.Stind_Ref);
1016 // Returns the size of type `t' if known, otherwise, 0
1018 public static int GetTypeSize (Type t)
1020 t = TypeManager.TypeToCoreType (t);
1021 if (t == TypeManager.int32_type ||
1022 t == TypeManager.uint32_type ||
1023 t == TypeManager.float_type)
1025 else if (t == TypeManager.int64_type ||
1026 t == TypeManager.uint64_type ||
1027 t == TypeManager.double_type)
1029 else if (t == TypeManager.byte_type ||
1030 t == TypeManager.sbyte_type ||
1031 t == TypeManager.bool_type)
1033 else if (t == TypeManager.short_type ||
1034 t == TypeManager.char_type ||
1035 t == TypeManager.ushort_type)
1037 else if (t == TypeManager.decimal_type)
1043 public static void Error_NegativeArrayIndex (Location loc)
1045 Report.Error (248, loc, "Cannot create an array with a negative size");
1048 protected void Error_CannotCallAbstractBase (string name)
1050 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1054 // Converts `source' to an int, uint, long or ulong.
1056 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1060 bool old_checked = ec.CheckState;
1061 ec.CheckState = true;
1063 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1064 if (target == null){
1065 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1066 if (target == null){
1067 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1068 if (target == null){
1069 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1071 source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1075 ec.CheckState = old_checked;
1078 // Only positive constants are allowed at compile time
1080 if (target is Constant){
1081 if (target is IntConstant){
1082 if (((IntConstant) target).Value < 0){
1083 Error_NegativeArrayIndex (loc);
1088 if (target is LongConstant){
1089 if (((LongConstant) target).Value < 0){
1090 Error_NegativeArrayIndex (loc);
1103 /// This is just a base class for expressions that can
1104 /// appear on statements (invocations, object creation,
1105 /// assignments, post/pre increment and decrement). The idea
1106 /// being that they would support an extra Emition interface that
1107 /// does not leave a result on the stack.
1109 public abstract class ExpressionStatement : Expression {
1111 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1113 Expression e = Resolve (ec);
1117 ExpressionStatement es = e as ExpressionStatement;
1119 Error (201, "Only assignment, call, increment, decrement and new object " +
1120 "expressions can be used as a statement");
1126 /// Requests the expression to be emitted in a `statement'
1127 /// context. This means that no new value is left on the
1128 /// stack after invoking this method (constrasted with
1129 /// Emit that will always leave a value on the stack).
1131 public abstract void EmitStatement (EmitContext ec);
1135 /// This kind of cast is used to encapsulate the child
1136 /// whose type is child.Type into an expression that is
1137 /// reported to return "return_type". This is used to encapsulate
1138 /// expressions which have compatible types, but need to be dealt
1139 /// at higher levels with.
1141 /// For example, a "byte" expression could be encapsulated in one
1142 /// of these as an "unsigned int". The type for the expression
1143 /// would be "unsigned int".
1146 public class EmptyCast : Expression {
1147 protected readonly Expression child;
1149 public Expression Child {
1155 public EmptyCast (Expression child, Type return_type)
1157 eclass = child.eclass;
1158 loc = child.Location;
1163 public override Expression DoResolve (EmitContext ec)
1165 // This should never be invoked, we are born in fully
1166 // initialized state.
1171 public override void Emit (EmitContext ec)
1176 public override bool GetAttributableValue (Type valueType, out object value)
1178 return child.GetAttributableValue (valueType, out value);
1183 /// This is a numeric cast to a Decimal
1185 public class CastToDecimal : EmptyCast {
1187 MethodInfo conversion_operator;
1189 public CastToDecimal (Expression child)
1190 : this (child, false)
1194 public CastToDecimal (Expression child, bool find_explicit)
1195 : base (child, TypeManager.decimal_type)
1197 conversion_operator = GetConversionOperator (find_explicit);
1199 if (conversion_operator == null)
1200 throw new InternalErrorException ("Outer conversion routine is out of sync");
1203 // Returns the implicit operator that converts from
1204 // 'child.Type' to System.Decimal.
1205 MethodInfo GetConversionOperator (bool find_explicit)
1207 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1209 MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1210 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1212 foreach (MethodInfo oper in mi) {
1213 ParameterData pd = TypeManager.GetParameterData (oper);
1215 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1221 public override void Emit (EmitContext ec)
1223 ILGenerator ig = ec.ig;
1226 ig.Emit (OpCodes.Call, conversion_operator);
1231 /// This is an explicit numeric cast from a Decimal
1233 public class CastFromDecimal : EmptyCast
1235 static IDictionary operators;
1237 public CastFromDecimal (Expression child, Type return_type)
1238 : base (child, return_type)
1240 if (child.Type != TypeManager.decimal_type)
1241 throw new InternalErrorException (
1242 "The expected type is Decimal, instead it is " + child.Type.FullName);
1245 // Returns the explicit operator that converts from an
1246 // express of type System.Decimal to 'type'.
1247 public Expression Resolve ()
1249 if (operators == null) {
1250 MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1251 TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1252 BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1254 operators = new System.Collections.Specialized.HybridDictionary ();
1255 foreach (MethodInfo oper in all_oper) {
1256 ParameterData pd = TypeManager.GetParameterData (oper);
1257 if (pd.ParameterType (0) == TypeManager.decimal_type)
1258 operators.Add (oper.ReturnType, oper);
1262 return operators.Contains (type) ? this : null;
1265 public override void Emit (EmitContext ec)
1267 ILGenerator ig = ec.ig;
1270 ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1275 // We need to special case this since an empty cast of
1276 // a NullLiteral is still a Constant
1278 public class NullCast : Constant {
1279 public Constant child;
1281 public NullCast (Constant child, Type return_type):
1282 base (Location.Null)
1284 eclass = child.eclass;
1289 override public string AsString ()
1294 public override object GetValue ()
1299 public override Expression DoResolve (EmitContext ec)
1301 // This should never be invoked, we are born in fully
1302 // initialized state.
1307 public override void Emit (EmitContext ec)
1312 public override Constant Increment ()
1314 throw new NotSupportedException ();
1317 public override bool IsDefaultValue {
1323 public override bool IsNegative {
1329 public override Constant Reduce (bool inCheckedContext, Type target_type)
1331 if (type == target_type)
1332 return child.Reduce (inCheckedContext, target_type);
1341 /// This class is used to wrap literals which belong inside Enums
1343 public class EnumConstant : Constant {
1344 public Constant Child;
1346 public EnumConstant (Constant child, Type enum_type):
1347 base (child.Location)
1349 eclass = child.eclass;
1354 public override Expression DoResolve (EmitContext ec)
1356 // This should never be invoked, we are born in fully
1357 // initialized state.
1362 public override void Emit (EmitContext ec)
1367 public override bool GetAttributableValue (Type valueType, out object value)
1369 value = GetTypedValue ();
1373 public override string GetSignatureForError()
1375 return TypeManager.CSharpName (Type);
1378 public override object GetValue ()
1380 return Child.GetValue ();
1383 public override object GetTypedValue ()
1385 // FIXME: runtime is not ready to work with just emited enums
1386 if (!RootContext.StdLib) {
1387 return Child.GetValue ();
1390 return System.Enum.ToObject (type, Child.GetValue ());
1393 public override string AsString ()
1395 return Child.AsString ();
1398 public override DoubleConstant ConvertToDouble ()
1400 return Child.ConvertToDouble ();
1403 public override FloatConstant ConvertToFloat ()
1405 return Child.ConvertToFloat ();
1408 public override ULongConstant ConvertToULong ()
1410 return Child.ConvertToULong ();
1413 public override LongConstant ConvertToLong ()
1415 return Child.ConvertToLong ();
1418 public override UIntConstant ConvertToUInt ()
1420 return Child.ConvertToUInt ();
1423 public override IntConstant ConvertToInt ()
1425 return Child.ConvertToInt ();
1428 public override Constant Increment()
1430 return new EnumConstant (Child.Increment (), type);
1433 public override bool IsDefaultValue {
1435 return Child.IsDefaultValue;
1439 public override bool IsZeroInteger {
1440 get { return Child.IsZeroInteger; }
1443 public override bool IsNegative {
1445 return Child.IsNegative;
1449 public override Constant Reduce(bool inCheckedContext, Type target_type)
1451 if (Child.Type == target_type)
1454 return Child.Reduce (inCheckedContext, target_type);
1457 public override Constant ToType (Type type, Location loc)
1460 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1461 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1464 if (type.UnderlyingSystemType != Child.Type)
1465 Child = Child.ToType (type.UnderlyingSystemType, loc);
1469 if (!Convert.ImplicitStandardConversionExists (this, type)){
1470 Error_ValueCannotBeConverted (loc, type, false);
1474 return Child.ToType (type, loc);
1480 /// This kind of cast is used to encapsulate Value Types in objects.
1482 /// The effect of it is to box the value type emitted by the previous
1485 public class BoxedCast : EmptyCast {
1487 public BoxedCast (Expression expr, Type target_type)
1488 : base (expr, target_type)
1490 eclass = ExprClass.Value;
1493 public override Expression DoResolve (EmitContext ec)
1495 // This should never be invoked, we are born in fully
1496 // initialized state.
1501 public override void Emit (EmitContext ec)
1505 ec.ig.Emit (OpCodes.Box, child.Type);
1509 public class UnboxCast : EmptyCast {
1510 public UnboxCast (Expression expr, Type return_type)
1511 : base (expr, return_type)
1515 public override Expression DoResolve (EmitContext ec)
1517 // This should never be invoked, we are born in fully
1518 // initialized state.
1523 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1525 if (right_side == EmptyExpression.LValueMemberAccess)
1526 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1527 return base.DoResolveLValue (ec, right_side);
1530 public override void Emit (EmitContext ec)
1533 ILGenerator ig = ec.ig;
1536 ig.Emit (OpCodes.Unbox, t);
1538 LoadFromPtr (ig, t);
1543 /// This is used to perform explicit numeric conversions.
1545 /// Explicit numeric conversions might trigger exceptions in a checked
1546 /// context, so they should generate the conv.ovf opcodes instead of
1549 public class ConvCast : EmptyCast {
1550 public enum Mode : byte {
1551 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1553 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1554 U2_I1, U2_U1, U2_I2, U2_CH,
1555 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1556 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1557 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1558 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1559 CH_I1, CH_U1, CH_I2,
1560 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1561 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1566 public ConvCast (Expression child, Type return_type, Mode m)
1567 : base (child, return_type)
1572 public override Expression DoResolve (EmitContext ec)
1574 // This should never be invoked, we are born in fully
1575 // initialized state.
1580 public override string ToString ()
1582 return String.Format ("ConvCast ({0}, {1})", mode, child);
1585 public override void Emit (EmitContext ec)
1587 ILGenerator ig = ec.ig;
1593 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1594 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1595 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1596 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1597 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1599 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1600 case Mode.U1_CH: /* nothing */ break;
1602 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1603 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1604 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1605 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1606 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1607 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1609 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1610 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1611 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1612 case Mode.U2_CH: /* nothing */ break;
1614 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1615 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1616 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1617 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1618 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1619 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1620 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1622 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1623 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1624 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1625 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1626 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1627 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1629 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1630 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1631 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1632 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1633 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1634 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1635 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1636 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1638 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1639 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1640 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1641 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1642 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1643 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1644 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1645 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1647 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1648 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1649 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1651 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1652 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1653 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1654 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1655 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1656 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1657 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1658 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1659 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1661 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1662 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1663 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1664 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1665 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1666 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1667 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1668 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1669 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1670 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1674 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1675 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1676 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1677 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1678 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1680 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1681 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1683 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1684 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1685 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1686 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1687 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1688 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1690 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1691 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1692 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1693 case Mode.U2_CH: /* nothing */ break;
1695 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1696 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1697 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1698 case Mode.I4_U4: /* nothing */ break;
1699 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1700 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1701 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1703 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1704 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1705 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1706 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1707 case Mode.U4_I4: /* nothing */ break;
1708 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1710 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1711 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1712 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1713 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1714 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1715 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1716 case Mode.I8_U8: /* nothing */ break;
1717 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1719 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1720 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1721 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1722 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1723 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1724 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1725 case Mode.U8_I8: /* nothing */ break;
1726 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1728 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1729 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1730 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1732 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1733 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1734 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1735 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1736 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1737 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1738 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1739 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1740 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1742 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1743 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1744 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1745 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1746 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1747 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1748 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1749 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1750 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1751 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1757 public class OpcodeCast : EmptyCast {
1761 public OpcodeCast (Expression child, Type return_type, OpCode op)
1762 : base (child, return_type)
1766 second_valid = false;
1769 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1770 : base (child, return_type)
1775 second_valid = true;
1778 public override Expression DoResolve (EmitContext ec)
1780 // This should never be invoked, we are born in fully
1781 // initialized state.
1786 public override void Emit (EmitContext ec)
1797 /// This kind of cast is used to encapsulate a child and cast it
1798 /// to the class requested
1800 public class ClassCast : EmptyCast {
1801 public ClassCast (Expression child, Type return_type)
1802 : base (child, return_type)
1807 public override Expression DoResolve (EmitContext ec)
1809 // This should never be invoked, we are born in fully
1810 // initialized state.
1815 public override void Emit (EmitContext ec)
1819 ec.ig.Emit (OpCodes.Castclass, type);
1825 /// SimpleName expressions are formed of a single word and only happen at the beginning
1826 /// of a dotted-name.
1828 public class SimpleName : Expression {
1832 public SimpleName (string name, Location l)
1838 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1840 if (ec.IsFieldInitializer)
1841 Report.Error (236, l,
1842 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1845 if (name.LastIndexOf ('.') > 0)
1846 name = name.Substring (name.LastIndexOf ('.') + 1);
1849 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1854 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1856 return resolved_to != null && resolved_to.Type != null &&
1857 resolved_to.Type.Name == Name &&
1858 (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1861 public override Expression DoResolve (EmitContext ec)
1863 return SimpleNameResolve (ec, null, false);
1866 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1868 return SimpleNameResolve (ec, right_side, false);
1872 public Expression DoResolve (EmitContext ec, bool intermediate)
1874 return SimpleNameResolve (ec, null, intermediate);
1877 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1879 int errors = Report.Errors;
1880 FullNamedExpression fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1884 if (silent || errors != Report.Errors)
1887 MemberCore mc = ec.DeclContainer.GetDefinition (Name);
1889 Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
1891 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
1897 // TODO: I am still not convinced about this. If someone else will need it
1898 // implement this as virtual property in MemberCore hierarchy
1899 string GetMemberType (MemberCore mc)
1901 if (mc is PropertyBase)
1905 if (mc is FieldBase)
1907 if (mc is MethodCore)
1909 if (mc is EnumMember)
1915 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1921 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
1925 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
1932 /// 7.5.2: Simple Names.
1934 /// Local Variables and Parameters are handled at
1935 /// parse time, so they never occur as SimpleNames.
1937 /// The `intermediate' flag is used by MemberAccess only
1938 /// and it is used to inform us that it is ok for us to
1939 /// avoid the static check, because MemberAccess might end
1940 /// up resolving the Name as a Type name and the access as
1941 /// a static type access.
1943 /// ie: Type Type; .... { Type.GetType (""); }
1945 /// Type is both an instance variable and a Type; Type.GetType
1946 /// is the static method not an instance method of type.
1948 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1950 Expression e = null;
1953 // Stage 1: Performed by the parser (binding to locals or parameters).
1955 Block current_block = ec.CurrentBlock;
1956 if (current_block != null){
1957 LocalInfo vi = current_block.GetLocalInfo (Name);
1959 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
1960 if (right_side != null) {
1961 return var.ResolveLValue (ec, right_side, loc);
1963 ResolveFlags rf = ResolveFlags.VariableOrValue;
1965 rf |= ResolveFlags.DisableFlowAnalysis;
1966 return var.Resolve (ec, rf);
1970 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
1972 if (right_side != null)
1973 return pref.ResolveLValue (ec, right_side, loc);
1975 return pref.Resolve (ec);
1980 // Stage 2: Lookup members
1983 DeclSpace lookup_ds = ec.DeclContainer;
1984 Type almost_matched_type = null;
1985 ArrayList almost_matched = null;
1987 if (lookup_ds.TypeBuilder == null)
1990 e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
1994 if (almost_matched == null && almostMatchedMembers.Count > 0) {
1995 almost_matched_type = lookup_ds.TypeBuilder;
1996 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
1999 lookup_ds =lookup_ds.Parent;
2000 } while (lookup_ds != null);
2002 if (e == null && ec.ContainerType != null)
2003 e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
2006 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2007 almost_matched_type = ec.ContainerType;
2008 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2010 e = ResolveAsTypeStep (ec, true);
2014 if (almost_matched != null)
2015 almostMatchedMembers = almost_matched;
2016 if (almost_matched_type == null)
2017 almost_matched_type = ec.ContainerType;
2018 MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
2025 if (e is MemberExpr) {
2026 MemberExpr me = (MemberExpr) e;
2029 if (me.IsInstance) {
2030 if (ec.IsStatic || ec.IsFieldInitializer) {
2032 // Note that an MemberExpr can be both IsInstance and IsStatic.
2033 // An unresolved MethodGroupExpr can contain both kinds of methods
2034 // and each predicate is true if the MethodGroupExpr contains
2035 // at least one of that kind of method.
2039 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2040 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2041 return EmptyExpression.Null;
2045 // Pass the buck to MemberAccess and Invocation.
2047 left = EmptyExpression.Null;
2049 left = ec.GetThis (loc);
2052 left = new TypeExpression (ec.ContainerType, loc);
2055 e = me.ResolveMemberAccess (ec, left, loc, null);
2059 me = e as MemberExpr;
2064 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2065 me.InstanceExpression.Type != me.DeclaringType &&
2066 !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
2067 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2068 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2069 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2073 return (right_side != null)
2074 ? me.DoResolveLValue (ec, right_side)
2075 : me.DoResolve (ec);
2081 public override void Emit (EmitContext ec)
2084 // If this is ever reached, then we failed to
2085 // find the name as a namespace
2088 Error (103, "The name `" + Name +
2089 "' does not exist in the class `" +
2090 ec.DeclContainer.Name + "'");
2093 public override string ToString ()
2098 public override string GetSignatureForError ()
2105 /// Represents a namespace or a type. The name of the class was inspired by
2106 /// section 10.8.1 (Fully Qualified Names).
2108 public abstract class FullNamedExpression : Expression {
2109 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2114 public abstract string FullName {
2120 /// Expression that evaluates to a type
2122 public abstract class TypeExpr : FullNamedExpression {
2123 override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2125 TypeExpr t = DoResolveAsTypeStep (ec);
2129 eclass = ExprClass.Type;
2133 override public Expression DoResolve (EmitContext ec)
2135 return ResolveAsTypeTerminal (ec, false);
2138 override public void Emit (EmitContext ec)
2140 throw new Exception ("Should never be called");
2143 public virtual bool CheckAccessLevel (DeclSpace ds)
2145 return ds.CheckAccessLevel (Type);
2148 public virtual bool AsAccessible (DeclSpace ds, int flags)
2150 return ds.AsAccessible (Type, flags);
2153 public virtual bool IsClass {
2154 get { return Type.IsClass; }
2157 public virtual bool IsValueType {
2158 get { return Type.IsValueType; }
2161 public virtual bool IsInterface {
2162 get { return Type.IsInterface; }
2165 public virtual bool IsSealed {
2166 get { return Type.IsSealed; }
2169 public virtual bool CanInheritFrom ()
2171 if (Type == TypeManager.enum_type ||
2172 (Type == TypeManager.value_type && RootContext.StdLib) ||
2173 Type == TypeManager.multicast_delegate_type ||
2174 Type == TypeManager.delegate_type ||
2175 Type == TypeManager.array_type)
2181 protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
2183 public abstract string Name {
2187 public override bool Equals (object obj)
2189 TypeExpr tobj = obj as TypeExpr;
2193 return Type == tobj.Type;
2196 public override int GetHashCode ()
2198 return Type.GetHashCode ();
2201 public override string ToString ()
2208 /// Fully resolved Expression that already evaluated to a type
2210 public class TypeExpression : TypeExpr {
2211 public TypeExpression (Type t, Location l)
2214 eclass = ExprClass.Type;
2218 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2223 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2228 public override string Name {
2229 get { return Type.ToString (); }
2232 public override string FullName {
2233 get { return Type.FullName; }
2238 /// Used to create types from a fully qualified name. These are just used
2239 /// by the parser to setup the core types. A TypeLookupExpression is always
2240 /// classified as a type.
2242 public sealed class TypeLookupExpression : TypeExpr {
2243 readonly string name;
2245 public TypeLookupExpression (string name)
2248 eclass = ExprClass.Type;
2251 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2253 // It's null for corlib compilation only
2255 return DoResolveAsTypeStep (ec);
2260 static readonly char [] dot_array = { '.' };
2261 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2263 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2265 string lookup_name = name;
2266 int pos = name.IndexOf ('.');
2268 rest = name.Substring (pos + 1);
2269 lookup_name = name.Substring (0, pos);
2272 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
2274 if (resolved != null && rest != null) {
2275 // Now handle the rest of the the name.
2276 string [] elements = rest.Split (dot_array);
2278 int count = elements.Length;
2280 while (i < count && resolved != null && resolved is Namespace) {
2281 Namespace ns = resolved as Namespace;
2282 element = elements [i++];
2283 lookup_name += "." + element;
2284 resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
2287 if (resolved != null && resolved is TypeExpr) {
2288 Type t = ((TypeExpr) resolved).Type;
2290 if (!ec.DeclContainer.CheckAccessLevel (t)) {
2292 lookup_name = t.FullName;
2299 t = TypeManager.GetNestedType (t, elements [i++]);
2304 if (resolved == null) {
2305 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2309 if (!(resolved is TypeExpr)) {
2310 resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
2314 type = resolved.Type;
2318 public override string Name {
2319 get { return name; }
2322 public override string FullName {
2323 get { return name; }
2327 public class TypeAliasExpression : TypeExpr {
2330 public TypeAliasExpression (TypeExpr texpr, Location l)
2333 loc = texpr.Location;
2335 eclass = ExprClass.Type;
2338 public override string Name {
2339 get { return texpr.Name; }
2342 public override string FullName {
2343 get { return texpr.FullName; }
2346 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2351 public override bool CheckAccessLevel (DeclSpace ds)
2353 return texpr.CheckAccessLevel (ds);
2356 public override bool AsAccessible (DeclSpace ds, int flags)
2358 return texpr.AsAccessible (ds, flags);
2361 public override bool IsClass {
2362 get { return texpr.IsClass; }
2365 public override bool IsValueType {
2366 get { return texpr.IsValueType; }
2369 public override bool IsInterface {
2370 get { return texpr.IsInterface; }
2373 public override bool IsSealed {
2374 get { return texpr.IsSealed; }
2379 /// This class denotes an expression which evaluates to a member
2380 /// of a struct or a class.
2382 public abstract class MemberExpr : Expression
2385 /// The name of this member.
2387 public abstract string Name {
2392 /// Whether this is an instance member.
2394 public abstract bool IsInstance {
2399 /// Whether this is a static member.
2401 public abstract bool IsStatic {
2406 /// The type which declares this member.
2408 public abstract Type DeclaringType {
2413 /// The instance expression associated with this member, if it's a
2414 /// non-static member.
2416 public Expression InstanceExpression;
2418 public static void error176 (Location loc, string name)
2420 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2421 "with an instance reference, qualify it with a type name instead", name);
2424 // TODO: possible optimalization
2425 // Cache resolved constant result in FieldBuilder <-> expression map
2426 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2427 SimpleName original)
2431 // original == null || original.Resolve (...) ==> left
2434 if (left is TypeExpr) {
2436 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2444 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2447 error176 (loc, GetSignatureForError ());
2451 InstanceExpression = left;
2456 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2461 if (InstanceExpression == EmptyExpression.Null) {
2462 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2466 if (InstanceExpression.Type.IsValueType) {
2467 if (InstanceExpression is IMemoryLocation) {
2468 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2470 LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
2471 InstanceExpression.Emit (ec);
2473 t.AddressOf (ec, AddressOp.Store);
2476 InstanceExpression.Emit (ec);
2478 if (prepare_for_load)
2479 ec.ig.Emit (OpCodes.Dup);
2484 /// MethodGroup Expression.
2486 /// This is a fully resolved expression that evaluates to a type
2488 public class MethodGroupExpr : MemberExpr {
2489 public MethodBase [] Methods;
2490 bool identical_type_name = false;
2493 public MethodGroupExpr (MemberInfo [] mi, Location l)
2495 Methods = new MethodBase [mi.Length];
2496 mi.CopyTo (Methods, 0);
2497 eclass = ExprClass.MethodGroup;
2498 type = TypeManager.object_type;
2502 public MethodGroupExpr (ArrayList list, Location l)
2504 Methods = new MethodBase [list.Count];
2507 list.CopyTo (Methods, 0);
2509 foreach (MemberInfo m in list){
2510 if (!(m is MethodBase)){
2511 Console.WriteLine ("Name " + m.Name);
2512 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2519 eclass = ExprClass.MethodGroup;
2520 type = TypeManager.object_type;
2523 public override Type DeclaringType {
2526 // The methods are arranged in this order:
2527 // derived type -> base type
2529 return Methods [0].DeclaringType;
2533 public bool IdenticalTypeName {
2535 return identical_type_name;
2539 identical_type_name = value;
2543 public bool IsBase {
2552 public override string GetSignatureForError ()
2554 return TypeManager.CSharpSignature (Methods [0]);
2557 public override string Name {
2559 return Methods [0].Name;
2563 public override bool IsInstance {
2565 foreach (MethodBase mb in Methods)
2573 public override bool IsStatic {
2575 foreach (MethodBase mb in Methods)
2583 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2584 SimpleName original)
2586 if (!(left is TypeExpr) &&
2587 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2588 IdenticalTypeName = true;
2590 return base.ResolveMemberAccess (ec, left, loc, original);
2593 override public Expression DoResolve (EmitContext ec)
2596 InstanceExpression = null;
2598 if (InstanceExpression != null) {
2599 InstanceExpression = InstanceExpression.DoResolve (ec);
2600 if (InstanceExpression == null)
2607 public void ReportUsageError ()
2609 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2610 Name + "()' is referenced without parentheses");
2613 override public void Emit (EmitContext ec)
2615 ReportUsageError ();
2618 bool RemoveMethods (bool keep_static)
2620 ArrayList smethods = new ArrayList ();
2622 foreach (MethodBase mb in Methods){
2623 if (mb.IsStatic == keep_static)
2627 if (smethods.Count == 0)
2630 Methods = new MethodBase [smethods.Count];
2631 smethods.CopyTo (Methods, 0);
2637 /// Removes any instance methods from the MethodGroup, returns
2638 /// false if the resulting set is empty.
2640 public bool RemoveInstanceMethods ()
2642 return RemoveMethods (true);
2646 /// Removes any static methods from the MethodGroup, returns
2647 /// false if the resulting set is empty.
2649 public bool RemoveStaticMethods ()
2651 return RemoveMethods (false);
2656 /// Fully resolved expression that evaluates to a Field
2658 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2659 public readonly FieldInfo FieldInfo;
2660 VariableInfo variable_info;
2662 LocalTemporary temp;
2664 bool in_initializer;
2666 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2669 this.in_initializer = in_initializer;
2672 public FieldExpr (FieldInfo fi, Location l)
2675 eclass = ExprClass.Variable;
2676 type = fi.FieldType;
2680 public override string Name {
2682 return FieldInfo.Name;
2686 public override bool IsInstance {
2688 return !FieldInfo.IsStatic;
2692 public override bool IsStatic {
2694 return FieldInfo.IsStatic;
2698 public override Type DeclaringType {
2700 return FieldInfo.DeclaringType;
2704 public override string GetSignatureForError ()
2706 return TypeManager.GetFullNameSignature (FieldInfo);
2709 public VariableInfo VariableInfo {
2711 return variable_info;
2715 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2716 SimpleName original)
2718 Type t = FieldInfo.FieldType;
2720 if (FieldInfo.IsLiteral || (FieldInfo.IsInitOnly && t == TypeManager.decimal_type)) {
2721 IConstant ic = TypeManager.GetConstant (FieldInfo);
2723 if (FieldInfo.IsLiteral) {
2724 ic = new ExternalConstant (FieldInfo);
2726 ic = ExternalConstant.CreateDecimal (FieldInfo);
2728 return base.ResolveMemberAccess (ec, left, loc, original);
2731 TypeManager.RegisterConstant (FieldInfo, ic);
2734 bool left_is_type = left is TypeExpr;
2735 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
2736 Report.SymbolRelatedToPreviousError (FieldInfo);
2737 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
2741 if (ic.ResolveValue ()) {
2742 if (!ec.IsInObsoleteScope)
2743 ic.CheckObsoleteness (loc);
2749 if (t.IsPointer && !ec.InUnsafe) {
2754 return base.ResolveMemberAccess (ec, left, loc, original);
2757 override public Expression DoResolve (EmitContext ec)
2759 return DoResolve (ec, false);
2762 Expression DoResolve (EmitContext ec, bool lvalue_instance)
2764 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
2765 if (FieldInfo.FieldType is TypeBuilder) {
2766 if (FieldInfo.IsStatic)
2767 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2768 GetSignatureForError ());
2770 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
2771 TypeManager.CSharpName (DeclaringType), Name);
2773 if (FieldInfo.IsStatic)
2774 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2777 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2783 if (!FieldInfo.IsStatic){
2784 if (InstanceExpression == null){
2786 // This can happen when referencing an instance field using
2787 // a fully qualified type expression: TypeName.InstanceField = xxx
2789 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
2793 // Resolve the field's instance expression while flow analysis is turned
2794 // off: when accessing a field "a.b", we must check whether the field
2795 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2797 if (lvalue_instance) {
2798 bool old_do_flow_analysis = ec.DoFlowAnalysis;
2799 ec.DoFlowAnalysis = false;
2800 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
2801 ec.DoFlowAnalysis = old_do_flow_analysis;
2803 ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
2804 InstanceExpression = InstanceExpression.Resolve (ec, rf);
2807 if (InstanceExpression == null)
2811 if (!in_initializer && !ec.IsFieldInitializer) {
2812 ObsoleteAttribute oa;
2813 FieldBase f = TypeManager.GetField (FieldInfo);
2815 if (!ec.IsInObsoleteScope)
2816 f.CheckObsoleteness (loc);
2818 // To be sure that type is external because we do not register generated fields
2819 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
2820 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
2822 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
2826 AnonymousContainer am = ec.CurrentAnonymousMethod;
2828 if (!FieldInfo.IsStatic){
2829 if (!am.IsIterator && (ec.TypeContainer is Struct)){
2830 Report.Error (1673, loc,
2831 "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",
2835 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
2836 ec.CaptureField (this);
2840 // If the instance expression is a local variable or parameter.
2841 IVariable var = InstanceExpression as IVariable;
2842 if ((var == null) || (var.VariableInfo == null))
2845 VariableInfo vi = var.VariableInfo;
2846 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
2849 variable_info = vi.GetSubStruct (FieldInfo.Name);
2853 void Report_AssignToReadonly (Expression right_side)
2857 bool need_error_sig = false;
2858 if (right_side == EmptyExpression.LValueMemberAccess) {
2861 msg = "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)";
2864 msg = "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)";
2866 need_error_sig = true;
2867 } else if (IsStatic) {
2869 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
2872 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
2876 Report.Error (code, loc, msg, GetSignatureForError ());
2878 Report.Error (code, loc, msg);
2881 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2883 IVariable var = InstanceExpression as IVariable;
2884 if ((var != null) && (var.VariableInfo != null))
2885 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
2887 bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
2889 Expression e = DoResolve (ec, lvalue_instance);
2894 FieldBase fb = TypeManager.GetField (FieldInfo);
2898 if (!FieldInfo.IsInitOnly)
2902 // InitOnly fields can only be assigned in constructors
2905 if (ec.IsConstructor){
2906 if (IsStatic && !ec.IsStatic)
2907 Report_AssignToReadonly (right_side);
2909 if (ec.ContainerType == FieldInfo.DeclaringType)
2913 Report_AssignToReadonly (right_side);
2918 public override void CheckMarshallByRefAccess (Type container)
2920 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
2921 Report.SymbolRelatedToPreviousError (DeclaringType);
2922 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",
2923 GetSignatureForError ());
2927 public bool VerifyFixed ()
2929 IVariable variable = InstanceExpression as IVariable;
2930 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
2931 // We defer the InstanceExpression check after the variable check to avoid a
2932 // separate null check on InstanceExpression.
2933 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
2936 public override int GetHashCode()
2938 return FieldInfo.GetHashCode ();
2941 public override bool Equals (object obj)
2943 FieldExpr fe = obj as FieldExpr;
2947 if (FieldInfo != fe.FieldInfo)
2950 if (InstanceExpression == null || fe.InstanceExpression == null)
2953 return InstanceExpression.Equals (fe.InstanceExpression);
2956 public void Emit (EmitContext ec, bool leave_copy)
2958 ILGenerator ig = ec.ig;
2959 bool is_volatile = false;
2961 FieldBase f = TypeManager.GetField (FieldInfo);
2963 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
2966 f.SetMemberIsUsed ();
2969 if (FieldInfo.IsStatic){
2971 ig.Emit (OpCodes.Volatile);
2973 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2976 EmitInstance (ec, false);
2979 ig.Emit (OpCodes.Volatile);
2981 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
2984 ig.Emit (OpCodes.Ldflda, FieldInfo);
2985 ig.Emit (OpCodes.Ldflda, ff.Element);
2988 ig.Emit (OpCodes.Ldfld, FieldInfo);
2993 ec.ig.Emit (OpCodes.Dup);
2994 if (!FieldInfo.IsStatic) {
2995 temp = new LocalTemporary (ec, this.Type);
3001 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3003 FieldAttributes fa = FieldInfo.Attributes;
3004 bool is_static = (fa & FieldAttributes.Static) != 0;
3005 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3006 ILGenerator ig = ec.ig;
3007 prepared = prepare_for_load;
3009 if (is_readonly && !ec.IsConstructor){
3010 Report_AssignToReadonly (source);
3014 EmitInstance (ec, prepare_for_load);
3018 ec.ig.Emit (OpCodes.Dup);
3019 if (!FieldInfo.IsStatic) {
3020 temp = new LocalTemporary (ec, this.Type);
3025 if (FieldInfo is FieldBuilder){
3026 FieldBase f = TypeManager.GetField (FieldInfo);
3028 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3029 ig.Emit (OpCodes.Volatile);
3036 ig.Emit (OpCodes.Stsfld, FieldInfo);
3038 ig.Emit (OpCodes.Stfld, FieldInfo);
3044 public override void Emit (EmitContext ec)
3049 public void AddressOf (EmitContext ec, AddressOp mode)
3051 ILGenerator ig = ec.ig;
3053 if (FieldInfo is FieldBuilder){
3054 FieldBase f = TypeManager.GetField (FieldInfo);
3056 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3057 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3058 f.GetSignatureForError ());
3062 if ((mode & AddressOp.Store) != 0)
3064 if ((mode & AddressOp.Load) != 0)
3065 f.SetMemberIsUsed ();
3070 // Handle initonly fields specially: make a copy and then
3071 // get the address of the copy.
3074 if (FieldInfo.IsInitOnly){
3076 if (ec.IsConstructor){
3077 if (FieldInfo.IsStatic){
3089 local = ig.DeclareLocal (type);
3090 ig.Emit (OpCodes.Stloc, local);
3091 ig.Emit (OpCodes.Ldloca, local);
3096 if (FieldInfo.IsStatic){
3097 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3099 EmitInstance (ec, false);
3100 ig.Emit (OpCodes.Ldflda, FieldInfo);
3106 // A FieldExpr whose address can not be taken
3108 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3109 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3113 public new void AddressOf (EmitContext ec, AddressOp mode)
3115 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3120 /// Expression that evaluates to a Property. The Assign class
3121 /// might set the `Value' expression if we are in an assignment.
3123 /// This is not an LValue because we need to re-write the expression, we
3124 /// can not take data from the stack and store it.
3126 public class PropertyExpr : MemberExpr, IAssignMethod {
3127 public readonly PropertyInfo PropertyInfo;
3130 // This is set externally by the `BaseAccess' class
3133 MethodInfo getter, setter;
3138 LocalTemporary temp;
3141 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3143 public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
3146 eclass = ExprClass.PropertyAccess;
3150 type = TypeManager.TypeToCoreType (pi.PropertyType);
3152 ResolveAccessors (containerType);
3155 public override string Name {
3157 return PropertyInfo.Name;
3161 public override bool IsInstance {
3167 public override bool IsStatic {
3173 public override Type DeclaringType {
3175 return PropertyInfo.DeclaringType;
3179 public override string GetSignatureForError ()
3181 return TypeManager.GetFullNameSignature (PropertyInfo);
3184 void FindAccessors (Type invocation_type)
3186 const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3187 BindingFlags.Static | BindingFlags.Instance |
3188 BindingFlags.DeclaredOnly;
3190 Type current = PropertyInfo.DeclaringType;
3191 for (; current != null; current = current.BaseType) {
3192 MemberInfo[] group = TypeManager.MemberLookup (
3193 invocation_type, invocation_type, current,
3194 MemberTypes.Property, flags, PropertyInfo.Name, null);
3199 if (group.Length != 1)
3200 // Oooops, can this ever happen ?
3203 PropertyInfo pi = (PropertyInfo) group [0];
3206 getter = pi.GetGetMethod (true);
3209 setter = pi.GetSetMethod (true);
3211 MethodInfo accessor = getter != null ? getter : setter;
3213 if (!accessor.IsVirtual)
3219 // We also perform the permission checking here, as the PropertyInfo does not
3220 // hold the information for the accessibility of its setter/getter
3222 // TODO: can use TypeManager.GetProperty to boost performance
3223 void ResolveAccessors (Type containerType)
3225 FindAccessors (containerType);
3227 if (getter != null) {
3228 IMethodData md = TypeManager.GetMethod (getter);
3230 md.SetMemberIsUsed ();
3232 AccessorTable [getter] = PropertyInfo;
3233 is_static = getter.IsStatic;
3236 if (setter != null) {
3237 IMethodData md = TypeManager.GetMethod (setter);
3239 md.SetMemberIsUsed ();
3241 AccessorTable [setter] = PropertyInfo;
3242 is_static = setter.IsStatic;
3246 bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
3249 InstanceExpression = null;
3253 if (InstanceExpression == null) {
3254 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3258 if (lvalue_instance)
3259 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3261 InstanceExpression = InstanceExpression.DoResolve (ec);
3262 if (InstanceExpression == null)
3265 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3267 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3268 InstanceExpression.Type != ec.ContainerType &&
3269 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3270 !InstanceExpression.Type.IsSubclassOf (ec.ContainerType)) {
3271 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3278 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3280 // TODO: correctly we should compare arguments but it will lead to bigger changes
3281 if (mi is MethodBuilder) {
3282 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3286 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3288 ParameterData iparams = TypeManager.GetParameterData (mi);
3289 sig.Append (getter ? "get_" : "set_");
3291 sig.Append (iparams.GetSignatureForError ());
3293 Report.SymbolRelatedToPreviousError (mi);
3294 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3295 Name, sig.ToString ());
3298 override public Expression DoResolve (EmitContext ec)
3303 if (getter != null){
3304 if (TypeManager.GetParameterData (getter).Count != 0){
3305 Error_PropertyNotFound (getter, true);
3310 if (getter == null){
3312 // The following condition happens if the PropertyExpr was
3313 // created, but is invalid (ie, the property is inaccessible),
3314 // and we did not want to embed the knowledge about this in
3315 // the caller routine. This only avoids double error reporting.
3320 if (InstanceExpression != EmptyExpression.Null) {
3321 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3322 TypeManager.GetFullNameSignature (PropertyInfo));
3327 bool must_do_cs1540_check = false;
3328 if (getter != null &&
3329 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3330 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3331 if (pm != null && pm.HasCustomAccessModifier) {
3332 Report.SymbolRelatedToPreviousError (pm);
3333 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3334 TypeManager.CSharpSignature (getter));
3337 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3341 if (!InstanceResolve (ec, false, must_do_cs1540_check))
3345 // Only base will allow this invocation to happen.
3347 if (IsBase && getter.IsAbstract) {
3348 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3352 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3362 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3364 if (right_side == EmptyExpression.OutAccess) {
3365 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
3366 GetSignatureForError ());
3370 if (right_side == EmptyExpression.LValueMemberAccess) {
3371 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
3372 GetSignatureForError ());
3376 if (setter == null){
3378 // The following condition happens if the PropertyExpr was
3379 // created, but is invalid (ie, the property is inaccessible),
3380 // and we did not want to embed the knowledge about this in
3381 // the caller routine. This only avoids double error reporting.
3385 Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
3386 GetSignatureForError ());
3390 if (TypeManager.GetParameterData (setter).Count != 1){
3391 Error_PropertyNotFound (setter, false);
3395 bool must_do_cs1540_check;
3396 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3397 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3398 if (pm != null && pm.HasCustomAccessModifier) {
3399 Report.SymbolRelatedToPreviousError (pm);
3400 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3401 TypeManager.CSharpSignature (setter));
3404 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3408 if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
3412 // Only base will allow this invocation to happen.
3414 if (IsBase && setter.IsAbstract){
3415 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3422 public override void Emit (EmitContext ec)
3427 public void Emit (EmitContext ec, bool leave_copy)
3430 // Special case: length of single dimension array property is turned into ldlen
3432 if ((getter == TypeManager.system_int_array_get_length) ||
3433 (getter == TypeManager.int_array_get_length)){
3434 Type iet = InstanceExpression.Type;
3437 // System.Array.Length can be called, but the Type does not
3438 // support invoking GetArrayRank, so test for that case first
3440 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3442 EmitInstance (ec, false);
3443 ec.ig.Emit (OpCodes.Ldlen);
3444 ec.ig.Emit (OpCodes.Conv_I4);
3449 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3452 ec.ig.Emit (OpCodes.Dup);
3454 temp = new LocalTemporary (ec, this.Type);
3461 // Implements the IAssignMethod interface for assignments
3463 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3465 Expression my_source = source;
3467 prepared = prepare_for_load;
3472 ec.ig.Emit (OpCodes.Dup);
3474 temp = new LocalTemporary (ec, this.Type);
3478 } else if (leave_copy) {
3481 temp = new LocalTemporary (ec, this.Type);
3487 ArrayList args = new ArrayList (1);
3488 args.Add (new Argument (my_source, Argument.AType.Expression));
3490 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3498 /// Fully resolved expression that evaluates to an Event
3500 public class EventExpr : MemberExpr {
3501 public readonly EventInfo EventInfo;
3504 MethodInfo add_accessor, remove_accessor;
3506 public EventExpr (EventInfo ei, Location loc)
3510 eclass = ExprClass.EventAccess;
3512 add_accessor = TypeManager.GetAddMethod (ei);
3513 remove_accessor = TypeManager.GetRemoveMethod (ei);
3515 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3518 if (EventInfo is MyEventBuilder){
3519 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3520 type = eb.EventType;
3523 type = EventInfo.EventHandlerType;
3526 public override string Name {
3528 return EventInfo.Name;
3532 public override bool IsInstance {
3538 public override bool IsStatic {
3544 public override Type DeclaringType {
3546 return EventInfo.DeclaringType;
3550 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3551 SimpleName original)
3554 // If the event is local to this class, we transform ourselves into a FieldExpr
3557 if (EventInfo.DeclaringType == ec.ContainerType ||
3558 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3559 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3562 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
3565 Report.Error (-200, loc, "Internal error!!");
3569 InstanceExpression = null;
3571 return ml.ResolveMemberAccess (ec, left, loc, original);
3575 return base.ResolveMemberAccess (ec, left, loc, original);
3579 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3582 InstanceExpression = null;
3586 if (InstanceExpression == null) {
3587 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3591 InstanceExpression = InstanceExpression.DoResolve (ec);
3592 if (InstanceExpression == null)
3596 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3597 // However, in the Event case, we reported a CS0122 instead.
3599 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3600 InstanceExpression.Type != ec.ContainerType &&
3601 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3602 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3609 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3611 return DoResolve (ec);
3614 public override Expression DoResolve (EmitContext ec)
3616 bool must_do_cs1540_check;
3617 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3618 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3619 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3623 if (!InstanceResolve (ec, must_do_cs1540_check))
3629 public override void Emit (EmitContext ec)
3631 if (InstanceExpression is This)
3632 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3634 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3635 "(except on the defining type)", Name);
3638 public override string GetSignatureForError ()
3640 return TypeManager.CSharpSignature (EventInfo);
3643 public void EmitAddOrRemove (EmitContext ec, Expression source)
3645 BinaryDelegate source_del = (BinaryDelegate) source;
3646 Expression handler = source_del.Right;
3648 Argument arg = new Argument (handler, Argument.AType.Expression);
3649 ArrayList args = new ArrayList ();
3653 if (source_del.IsAddition)
3654 Invocation.EmitCall (
3655 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3657 Invocation.EmitCall (
3658 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3663 public class TemporaryVariable : Expression, IMemoryLocation
3667 public TemporaryVariable (Type type, Location loc)
3671 eclass = ExprClass.Value;
3674 public override Expression DoResolve (EmitContext ec)
3679 TypeExpr te = new TypeExpression (type, loc);
3680 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3681 if (!li.Resolve (ec))
3684 AnonymousContainer am = ec.CurrentAnonymousMethod;
3685 if ((am != null) && am.IsIterator)
3686 ec.CaptureVariable (li);
3691 public override void Emit (EmitContext ec)
3693 ILGenerator ig = ec.ig;
3695 if (li.FieldBuilder != null) {
3696 ig.Emit (OpCodes.Ldarg_0);
3697 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3699 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3703 public void EmitLoadAddress (EmitContext ec)
3705 ILGenerator ig = ec.ig;
3707 if (li.FieldBuilder != null) {
3708 ig.Emit (OpCodes.Ldarg_0);
3709 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3711 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3715 public void Store (EmitContext ec, Expression right_side)
3717 if (li.FieldBuilder != null)
3718 ec.ig.Emit (OpCodes.Ldarg_0);
3720 right_side.Emit (ec);
3721 if (li.FieldBuilder != null) {
3722 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3724 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3728 public void EmitThis (EmitContext ec)
3730 if (li.FieldBuilder != null) {
3731 ec.ig.Emit (OpCodes.Ldarg_0);
3735 public void EmitStore (ILGenerator ig)
3737 if (li.FieldBuilder != null)
3738 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3740 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3743 public void AddressOf (EmitContext ec, AddressOp mode)
3745 EmitLoadAddress (ec);