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 (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 (out object value)
1178 return child.GetAttributableValue (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 (EmitContext ec, Type target_type)
1331 if (type == target_type)
1332 return child.Reduce (ec, 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 string GetSignatureForError()
1369 return TypeManager.CSharpName (Type);
1372 public override object GetValue ()
1374 return Child.GetValue ();
1377 public override object GetTypedValue ()
1379 // FIXME: runtime is not ready to work with just emited enums
1380 if (!RootContext.StdLib) {
1381 return Child.GetValue ();
1384 return System.Enum.ToObject (type, Child.GetValue ());
1387 public override string AsString ()
1389 return Child.AsString ();
1392 public override DoubleConstant ConvertToDouble ()
1394 return Child.ConvertToDouble ();
1397 public override FloatConstant ConvertToFloat ()
1399 return Child.ConvertToFloat ();
1402 public override ULongConstant ConvertToULong ()
1404 return Child.ConvertToULong ();
1407 public override LongConstant ConvertToLong ()
1409 return Child.ConvertToLong ();
1412 public override UIntConstant ConvertToUInt ()
1414 return Child.ConvertToUInt ();
1417 public override IntConstant ConvertToInt ()
1419 return Child.ConvertToInt ();
1422 public override Constant Increment()
1424 return new EnumConstant (Child.Increment (), type);
1427 public override bool IsDefaultValue {
1429 return Child.IsDefaultValue;
1433 public override bool IsZeroInteger {
1434 get { return Child.IsZeroInteger; }
1437 public override bool IsNegative {
1439 return Child.IsNegative;
1443 public override Constant Reduce(EmitContext ec, Type target_type)
1445 if (Child.Type == target_type)
1448 return Child.Reduce (ec, target_type);
1451 public override Constant ToType (Type type, Location loc)
1454 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1455 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1458 if (type.UnderlyingSystemType != Child.Type)
1459 Child = Child.ToType (type.UnderlyingSystemType, loc);
1463 if (!Convert.ImplicitStandardConversionExists (this, type)){
1464 Error_ValueCannotBeConverted (loc, type, false);
1468 return Child.ToType (type, loc);
1474 /// This kind of cast is used to encapsulate Value Types in objects.
1476 /// The effect of it is to box the value type emitted by the previous
1479 public class BoxedCast : EmptyCast {
1481 public BoxedCast (Expression expr, Type target_type)
1482 : base (expr, target_type)
1484 eclass = ExprClass.Value;
1487 public override Expression DoResolve (EmitContext ec)
1489 // This should never be invoked, we are born in fully
1490 // initialized state.
1495 public override void Emit (EmitContext ec)
1499 ec.ig.Emit (OpCodes.Box, child.Type);
1503 public class UnboxCast : EmptyCast {
1504 public UnboxCast (Expression expr, Type return_type)
1505 : base (expr, return_type)
1509 public override Expression DoResolve (EmitContext ec)
1511 // This should never be invoked, we are born in fully
1512 // initialized state.
1517 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1519 if (right_side == EmptyExpression.LValueMemberAccess)
1520 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1521 return base.DoResolveLValue (ec, right_side);
1524 public override void Emit (EmitContext ec)
1527 ILGenerator ig = ec.ig;
1530 ig.Emit (OpCodes.Unbox, t);
1532 LoadFromPtr (ig, t);
1537 /// This is used to perform explicit numeric conversions.
1539 /// Explicit numeric conversions might trigger exceptions in a checked
1540 /// context, so they should generate the conv.ovf opcodes instead of
1543 public class ConvCast : EmptyCast {
1544 public enum Mode : byte {
1545 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1547 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1548 U2_I1, U2_U1, U2_I2, U2_CH,
1549 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1550 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1551 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1552 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1553 CH_I1, CH_U1, CH_I2,
1554 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1555 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1560 public ConvCast (Expression child, Type return_type, Mode m)
1561 : base (child, return_type)
1566 public override Expression DoResolve (EmitContext ec)
1568 // This should never be invoked, we are born in fully
1569 // initialized state.
1574 public override string ToString ()
1576 return String.Format ("ConvCast ({0}, {1})", mode, child);
1579 public override void Emit (EmitContext ec)
1581 ILGenerator ig = ec.ig;
1587 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1588 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1589 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1590 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1591 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1593 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1594 case Mode.U1_CH: /* nothing */ break;
1596 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1597 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1598 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1599 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1600 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1601 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1603 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1604 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1605 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1606 case Mode.U2_CH: /* nothing */ break;
1608 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1609 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1610 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1611 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1612 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1613 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1614 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1616 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1617 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1618 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1619 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1620 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1621 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1623 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1624 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1625 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1626 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1627 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1628 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1629 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1630 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1632 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1633 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1634 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1635 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1636 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1637 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1638 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1639 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1641 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1642 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1643 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1645 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1646 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1647 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1648 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1649 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1650 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1651 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1652 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1653 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1655 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1656 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1657 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1658 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1659 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1660 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1661 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1662 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1663 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1664 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1668 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1669 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1670 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1671 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1672 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1674 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1675 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1677 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1678 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1679 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1680 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1681 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1682 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1684 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1685 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1686 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1687 case Mode.U2_CH: /* nothing */ break;
1689 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1690 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1691 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1692 case Mode.I4_U4: /* nothing */ break;
1693 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1694 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1695 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1697 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1698 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1699 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1700 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1701 case Mode.U4_I4: /* nothing */ break;
1702 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1704 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1705 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1706 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1707 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1708 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1709 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1710 case Mode.I8_U8: /* nothing */ break;
1711 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1713 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1714 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1715 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1716 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1717 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1718 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1719 case Mode.U8_I8: /* nothing */ break;
1720 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1722 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1723 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1724 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1726 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1727 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1728 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1729 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1730 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1731 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1732 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1733 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1734 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1736 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1737 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1738 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1739 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1740 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1741 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1742 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1743 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1744 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1745 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1751 public class OpcodeCast : EmptyCast {
1755 public OpcodeCast (Expression child, Type return_type, OpCode op)
1756 : base (child, return_type)
1760 second_valid = false;
1763 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1764 : base (child, return_type)
1769 second_valid = true;
1772 public override Expression DoResolve (EmitContext ec)
1774 // This should never be invoked, we are born in fully
1775 // initialized state.
1780 public override void Emit (EmitContext ec)
1791 /// This kind of cast is used to encapsulate a child and cast it
1792 /// to the class requested
1794 public class ClassCast : EmptyCast {
1795 public ClassCast (Expression child, Type return_type)
1796 : base (child, return_type)
1801 public override Expression DoResolve (EmitContext ec)
1803 // This should never be invoked, we are born in fully
1804 // initialized state.
1809 public override void Emit (EmitContext ec)
1813 ec.ig.Emit (OpCodes.Castclass, type);
1819 /// SimpleName expressions are formed of a single word and only happen at the beginning
1820 /// of a dotted-name.
1822 public class SimpleName : Expression {
1826 public SimpleName (string name, Location l)
1832 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1834 if (ec.IsFieldInitializer)
1835 Report.Error (236, l,
1836 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1839 if (name.LastIndexOf ('.') > 0)
1840 name = name.Substring (name.LastIndexOf ('.') + 1);
1843 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1848 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1850 return resolved_to != null && resolved_to.Type != null &&
1851 resolved_to.Type.Name == Name &&
1852 (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1855 public override Expression DoResolve (EmitContext ec)
1857 return SimpleNameResolve (ec, null, false);
1860 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1862 return SimpleNameResolve (ec, right_side, false);
1866 public Expression DoResolve (EmitContext ec, bool intermediate)
1868 return SimpleNameResolve (ec, null, intermediate);
1871 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1873 int errors = Report.Errors;
1874 FullNamedExpression fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1878 if (silent || errors != Report.Errors)
1881 MemberCore mc = ec.DeclContainer.GetDefinition (Name);
1883 Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
1885 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
1891 // TODO: I am still not convinced about this. If someone else will need it
1892 // implement this as virtual property in MemberCore hierarchy
1893 string GetMemberType (MemberCore mc)
1895 if (mc is PropertyBase)
1899 if (mc is FieldBase)
1901 if (mc is MethodCore)
1903 if (mc is EnumMember)
1909 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1915 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
1919 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
1926 /// 7.5.2: Simple Names.
1928 /// Local Variables and Parameters are handled at
1929 /// parse time, so they never occur as SimpleNames.
1931 /// The `intermediate' flag is used by MemberAccess only
1932 /// and it is used to inform us that it is ok for us to
1933 /// avoid the static check, because MemberAccess might end
1934 /// up resolving the Name as a Type name and the access as
1935 /// a static type access.
1937 /// ie: Type Type; .... { Type.GetType (""); }
1939 /// Type is both an instance variable and a Type; Type.GetType
1940 /// is the static method not an instance method of type.
1942 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
1944 Expression e = null;
1947 // Stage 1: Performed by the parser (binding to locals or parameters).
1949 Block current_block = ec.CurrentBlock;
1950 if (current_block != null){
1951 LocalInfo vi = current_block.GetLocalInfo (Name);
1953 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
1954 if (right_side != null) {
1955 return var.ResolveLValue (ec, right_side, loc);
1957 ResolveFlags rf = ResolveFlags.VariableOrValue;
1959 rf |= ResolveFlags.DisableFlowAnalysis;
1960 return var.Resolve (ec, rf);
1964 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
1966 if (right_side != null)
1967 return pref.ResolveLValue (ec, right_side, loc);
1969 return pref.Resolve (ec);
1974 // Stage 2: Lookup members
1977 DeclSpace lookup_ds = ec.DeclContainer;
1978 Type almost_matched_type = null;
1979 ArrayList almost_matched = null;
1981 if (lookup_ds.TypeBuilder == null)
1984 e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
1988 if (almost_matched == null && almostMatchedMembers.Count > 0) {
1989 almost_matched_type = lookup_ds.TypeBuilder;
1990 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
1993 lookup_ds =lookup_ds.Parent;
1994 } while (lookup_ds != null);
1996 if (e == null && ec.ContainerType != null)
1997 e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
2000 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2001 almost_matched_type = ec.ContainerType;
2002 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2004 e = ResolveAsTypeStep (ec, true);
2008 if (almost_matched != null)
2009 almostMatchedMembers = almost_matched;
2010 if (almost_matched_type == null)
2011 almost_matched_type = ec.ContainerType;
2012 MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
2019 if (e is MemberExpr) {
2020 MemberExpr me = (MemberExpr) e;
2023 if (me.IsInstance) {
2024 if (ec.IsStatic || ec.IsFieldInitializer) {
2026 // Note that an MemberExpr can be both IsInstance and IsStatic.
2027 // An unresolved MethodGroupExpr can contain both kinds of methods
2028 // and each predicate is true if the MethodGroupExpr contains
2029 // at least one of that kind of method.
2033 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2034 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2035 return EmptyExpression.Null;
2039 // Pass the buck to MemberAccess and Invocation.
2041 left = EmptyExpression.Null;
2043 left = ec.GetThis (loc);
2046 left = new TypeExpression (ec.ContainerType, loc);
2049 e = me.ResolveMemberAccess (ec, left, loc, null);
2053 me = e as MemberExpr;
2058 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2059 me.InstanceExpression.Type != me.DeclaringType &&
2060 !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType) &&
2061 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2062 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2063 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2067 return (right_side != null)
2068 ? me.DoResolveLValue (ec, right_side)
2069 : me.DoResolve (ec);
2075 public override void Emit (EmitContext ec)
2078 // If this is ever reached, then we failed to
2079 // find the name as a namespace
2082 Error (103, "The name `" + Name +
2083 "' does not exist in the class `" +
2084 ec.DeclContainer.Name + "'");
2087 public override string ToString ()
2092 public override string GetSignatureForError ()
2099 /// Represents a namespace or a type. The name of the class was inspired by
2100 /// section 10.8.1 (Fully Qualified Names).
2102 public abstract class FullNamedExpression : Expression {
2103 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2108 public abstract string FullName {
2114 /// Expression that evaluates to a type
2116 public abstract class TypeExpr : FullNamedExpression {
2117 override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2119 TypeExpr t = DoResolveAsTypeStep (ec);
2123 eclass = ExprClass.Type;
2127 override public Expression DoResolve (EmitContext ec)
2129 return ResolveAsTypeTerminal (ec, false);
2132 override public void Emit (EmitContext ec)
2134 throw new Exception ("Should never be called");
2137 public virtual bool CheckAccessLevel (DeclSpace ds)
2139 return ds.CheckAccessLevel (Type);
2142 public virtual bool AsAccessible (DeclSpace ds, int flags)
2144 return ds.AsAccessible (Type, flags);
2147 public virtual bool IsClass {
2148 get { return Type.IsClass; }
2151 public virtual bool IsValueType {
2152 get { return Type.IsValueType; }
2155 public virtual bool IsInterface {
2156 get { return Type.IsInterface; }
2159 public virtual bool IsSealed {
2160 get { return Type.IsSealed; }
2163 public virtual bool CanInheritFrom ()
2165 if (Type == TypeManager.enum_type ||
2166 (Type == TypeManager.value_type && RootContext.StdLib) ||
2167 Type == TypeManager.multicast_delegate_type ||
2168 Type == TypeManager.delegate_type ||
2169 Type == TypeManager.array_type)
2175 public abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
2177 public abstract string Name {
2181 public override bool Equals (object obj)
2183 TypeExpr tobj = obj as TypeExpr;
2187 return Type == tobj.Type;
2190 public override int GetHashCode ()
2192 return Type.GetHashCode ();
2195 public override string ToString ()
2202 /// Fully resolved Expression that already evaluated to a type
2204 public class TypeExpression : TypeExpr {
2205 public TypeExpression (Type t, Location l)
2208 eclass = ExprClass.Type;
2212 public override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2217 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2222 public override string Name {
2223 get { return Type.ToString (); }
2226 public override string FullName {
2227 get { return Type.FullName; }
2232 /// Used to create types from a fully qualified name. These are just used
2233 /// by the parser to setup the core types. A TypeLookupExpression is always
2234 /// classified as a type.
2236 public sealed class TypeLookupExpression : TypeExpr {
2237 readonly string name;
2239 public TypeLookupExpression (string name)
2242 eclass = ExprClass.Type;
2245 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2247 // It's null for corlib compilation only
2249 return DoResolveAsTypeStep (ec);
2254 static readonly char [] dot_array = { '.' };
2255 public override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2257 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2259 string lookup_name = name;
2260 int pos = name.IndexOf ('.');
2262 rest = name.Substring (pos + 1);
2263 lookup_name = name.Substring (0, pos);
2266 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
2268 if (resolved != null && rest != null) {
2269 // Now handle the rest of the the name.
2270 string [] elements = rest.Split (dot_array);
2272 int count = elements.Length;
2274 while (i < count && resolved != null && resolved is Namespace) {
2275 Namespace ns = resolved as Namespace;
2276 element = elements [i++];
2277 lookup_name += "." + element;
2278 resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
2281 if (resolved != null && resolved is TypeExpr) {
2282 Type t = ((TypeExpr) resolved).Type;
2284 if (!ec.DeclContainer.CheckAccessLevel (t)) {
2286 lookup_name = t.FullName;
2293 t = TypeManager.GetNestedType (t, elements [i++]);
2298 if (resolved == null) {
2299 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2303 if (!(resolved is TypeExpr)) {
2304 resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
2308 type = resolved.Type;
2312 public override string Name {
2313 get { return name; }
2316 public override string FullName {
2317 get { return name; }
2321 public class TypeAliasExpression : TypeExpr {
2324 public TypeAliasExpression (TypeExpr texpr, Location l)
2327 loc = texpr.Location;
2329 eclass = ExprClass.Type;
2332 public override string Name {
2333 get { return texpr.Name; }
2336 public override string FullName {
2337 get { return texpr.FullName; }
2340 public override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2345 public override bool CheckAccessLevel (DeclSpace ds)
2347 return texpr.CheckAccessLevel (ds);
2350 public override bool AsAccessible (DeclSpace ds, int flags)
2352 return texpr.AsAccessible (ds, flags);
2355 public override bool IsClass {
2356 get { return texpr.IsClass; }
2359 public override bool IsValueType {
2360 get { return texpr.IsValueType; }
2363 public override bool IsInterface {
2364 get { return texpr.IsInterface; }
2367 public override bool IsSealed {
2368 get { return texpr.IsSealed; }
2373 /// This class denotes an expression which evaluates to a member
2374 /// of a struct or a class.
2376 public abstract class MemberExpr : Expression
2379 /// The name of this member.
2381 public abstract string Name {
2386 /// Whether this is an instance member.
2388 public abstract bool IsInstance {
2393 /// Whether this is a static member.
2395 public abstract bool IsStatic {
2400 /// The type which declares this member.
2402 public abstract Type DeclaringType {
2407 /// The instance expression associated with this member, if it's a
2408 /// non-static member.
2410 public Expression InstanceExpression;
2412 public static void error176 (Location loc, string name)
2414 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2415 "with an instance reference, qualify it with a type name instead", name);
2418 // TODO: possible optimalization
2419 // Cache resolved constant result in FieldBuilder <-> expression map
2420 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2421 SimpleName original)
2425 // original == null || original.Resolve (...) ==> left
2428 if (left is TypeExpr) {
2430 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2438 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2441 error176 (loc, GetSignatureForError ());
2445 InstanceExpression = left;
2450 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2455 if (InstanceExpression == EmptyExpression.Null) {
2456 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2460 if (InstanceExpression.Type.IsValueType) {
2461 if (InstanceExpression is IMemoryLocation) {
2462 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2464 LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
2465 InstanceExpression.Emit (ec);
2467 t.AddressOf (ec, AddressOp.Store);
2470 InstanceExpression.Emit (ec);
2472 if (prepare_for_load)
2473 ec.ig.Emit (OpCodes.Dup);
2478 /// MethodGroup Expression.
2480 /// This is a fully resolved expression that evaluates to a type
2482 public class MethodGroupExpr : MemberExpr {
2483 public MethodBase [] Methods;
2484 bool identical_type_name = false;
2487 public MethodGroupExpr (MemberInfo [] mi, Location l)
2489 Methods = new MethodBase [mi.Length];
2490 mi.CopyTo (Methods, 0);
2491 eclass = ExprClass.MethodGroup;
2492 type = TypeManager.object_type;
2496 public MethodGroupExpr (ArrayList list, Location l)
2498 Methods = new MethodBase [list.Count];
2501 list.CopyTo (Methods, 0);
2503 foreach (MemberInfo m in list){
2504 if (!(m is MethodBase)){
2505 Console.WriteLine ("Name " + m.Name);
2506 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2513 eclass = ExprClass.MethodGroup;
2514 type = TypeManager.object_type;
2517 public override Type DeclaringType {
2520 // The methods are arranged in this order:
2521 // derived type -> base type
2523 return Methods [0].DeclaringType;
2527 public bool IdenticalTypeName {
2529 return identical_type_name;
2533 identical_type_name = value;
2537 public bool IsBase {
2546 public override string GetSignatureForError ()
2548 return TypeManager.CSharpSignature (Methods [0]);
2551 public override string Name {
2553 return Methods [0].Name;
2557 public override bool IsInstance {
2559 foreach (MethodBase mb in Methods)
2567 public override bool IsStatic {
2569 foreach (MethodBase mb in Methods)
2577 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2578 SimpleName original)
2580 if (!(left is TypeExpr) &&
2581 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2582 IdenticalTypeName = true;
2584 return base.ResolveMemberAccess (ec, left, loc, original);
2587 override public Expression DoResolve (EmitContext ec)
2590 InstanceExpression = null;
2592 if (InstanceExpression != null) {
2593 InstanceExpression = InstanceExpression.DoResolve (ec);
2594 if (InstanceExpression == null)
2601 public void ReportUsageError ()
2603 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2604 Name + "()' is referenced without parentheses");
2607 override public void Emit (EmitContext ec)
2609 ReportUsageError ();
2612 bool RemoveMethods (bool keep_static)
2614 ArrayList smethods = new ArrayList ();
2616 foreach (MethodBase mb in Methods){
2617 if (mb.IsStatic == keep_static)
2621 if (smethods.Count == 0)
2624 Methods = new MethodBase [smethods.Count];
2625 smethods.CopyTo (Methods, 0);
2631 /// Removes any instance methods from the MethodGroup, returns
2632 /// false if the resulting set is empty.
2634 public bool RemoveInstanceMethods ()
2636 return RemoveMethods (true);
2640 /// Removes any static methods from the MethodGroup, returns
2641 /// false if the resulting set is empty.
2643 public bool RemoveStaticMethods ()
2645 return RemoveMethods (false);
2650 /// Fully resolved expression that evaluates to a Field
2652 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2653 public readonly FieldInfo FieldInfo;
2654 VariableInfo variable_info;
2656 LocalTemporary temp;
2658 bool in_initializer;
2660 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2663 this.in_initializer = in_initializer;
2666 public FieldExpr (FieldInfo fi, Location l)
2669 eclass = ExprClass.Variable;
2670 type = fi.FieldType;
2674 public override string Name {
2676 return FieldInfo.Name;
2680 public override bool IsInstance {
2682 return !FieldInfo.IsStatic;
2686 public override bool IsStatic {
2688 return FieldInfo.IsStatic;
2692 public override Type DeclaringType {
2694 return FieldInfo.DeclaringType;
2698 public override string GetSignatureForError ()
2700 return TypeManager.GetFullNameSignature (FieldInfo);
2703 public VariableInfo VariableInfo {
2705 return variable_info;
2709 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2710 SimpleName original)
2712 Type t = FieldInfo.FieldType;
2714 if (FieldInfo.IsLiteral || (FieldInfo.IsInitOnly && t == TypeManager.decimal_type)) {
2715 IConstant ic = TypeManager.GetConstant (FieldInfo);
2717 if (FieldInfo.IsLiteral) {
2718 ic = new ExternalConstant (FieldInfo);
2720 ic = ExternalConstant.CreateDecimal (FieldInfo);
2722 return base.ResolveMemberAccess (ec, left, loc, original);
2725 TypeManager.RegisterConstant (FieldInfo, ic);
2728 bool left_is_type = left is TypeExpr;
2729 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
2730 Report.SymbolRelatedToPreviousError (FieldInfo);
2731 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
2735 if (ic.ResolveValue ()) {
2736 if (!ec.IsInObsoleteScope)
2737 ic.CheckObsoleteness (loc);
2743 if (t.IsPointer && !ec.InUnsafe) {
2748 return base.ResolveMemberAccess (ec, left, loc, original);
2751 override public Expression DoResolve (EmitContext ec)
2753 return DoResolve (ec, false);
2756 Expression DoResolve (EmitContext ec, bool lvalue_instance)
2758 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
2759 if (FieldInfo.FieldType is TypeBuilder) {
2760 if (FieldInfo.IsStatic)
2761 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2762 GetSignatureForError ());
2764 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
2765 TypeManager.CSharpName (DeclaringType), Name);
2767 if (FieldInfo.IsStatic)
2768 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
2771 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
2777 if (!FieldInfo.IsStatic){
2778 if (InstanceExpression == null){
2780 // This can happen when referencing an instance field using
2781 // a fully qualified type expression: TypeName.InstanceField = xxx
2783 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
2787 // Resolve the field's instance expression while flow analysis is turned
2788 // off: when accessing a field "a.b", we must check whether the field
2789 // "a.b" is initialized, not whether the whole struct "a" is initialized.
2791 if (lvalue_instance) {
2792 bool old_do_flow_analysis = ec.DoFlowAnalysis;
2793 ec.DoFlowAnalysis = false;
2794 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
2795 ec.DoFlowAnalysis = old_do_flow_analysis;
2797 ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
2798 InstanceExpression = InstanceExpression.Resolve (ec, rf);
2801 if (InstanceExpression == null)
2805 if (!in_initializer && !ec.IsFieldInitializer) {
2806 ObsoleteAttribute oa;
2807 FieldBase f = TypeManager.GetField (FieldInfo);
2809 if (!ec.IsInObsoleteScope)
2810 f.CheckObsoleteness (loc);
2812 // To be sure that type is external because we do not register generated fields
2813 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
2814 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
2816 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
2820 AnonymousContainer am = ec.CurrentAnonymousMethod;
2822 if (!FieldInfo.IsStatic){
2823 if (!am.IsIterator && (ec.TypeContainer is Struct)){
2824 Report.Error (1673, loc,
2825 "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",
2829 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
2830 ec.CaptureField (this);
2834 // If the instance expression is a local variable or parameter.
2835 IVariable var = InstanceExpression as IVariable;
2836 if ((var == null) || (var.VariableInfo == null))
2839 VariableInfo vi = var.VariableInfo;
2840 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
2843 variable_info = vi.GetSubStruct (FieldInfo.Name);
2847 void Report_AssignToReadonly (Expression right_side)
2851 bool need_error_sig = false;
2852 if (right_side == EmptyExpression.LValueMemberAccess) {
2855 msg = "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)";
2858 msg = "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)";
2860 need_error_sig = true;
2861 } else if (IsStatic) {
2863 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
2866 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
2870 Report.Error (code, loc, msg, GetSignatureForError ());
2872 Report.Error (code, loc, msg);
2875 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2877 IVariable var = InstanceExpression as IVariable;
2878 if ((var != null) && (var.VariableInfo != null))
2879 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
2881 bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
2883 Expression e = DoResolve (ec, lvalue_instance);
2888 FieldBase fb = TypeManager.GetField (FieldInfo);
2892 if (!FieldInfo.IsInitOnly)
2896 // InitOnly fields can only be assigned in constructors
2899 if (ec.IsConstructor){
2900 if (IsStatic && !ec.IsStatic)
2901 Report_AssignToReadonly (right_side);
2903 if (ec.ContainerType == FieldInfo.DeclaringType)
2907 Report_AssignToReadonly (right_side);
2912 public override void CheckMarshallByRefAccess (Type container)
2914 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
2915 Report.SymbolRelatedToPreviousError (DeclaringType);
2916 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",
2917 GetSignatureForError ());
2921 public bool VerifyFixed ()
2923 IVariable variable = InstanceExpression as IVariable;
2924 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
2925 // We defer the InstanceExpression check after the variable check to avoid a
2926 // separate null check on InstanceExpression.
2927 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
2930 public override int GetHashCode()
2932 return FieldInfo.GetHashCode ();
2935 public override bool Equals (object obj)
2937 FieldExpr fe = obj as FieldExpr;
2941 if (FieldInfo != fe.FieldInfo)
2944 if (InstanceExpression == null || fe.InstanceExpression == null)
2947 return InstanceExpression.Equals (fe.InstanceExpression);
2950 public void Emit (EmitContext ec, bool leave_copy)
2952 ILGenerator ig = ec.ig;
2953 bool is_volatile = false;
2955 if (FieldInfo is FieldBuilder){
2956 FieldBase f = TypeManager.GetField (FieldInfo);
2958 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
2961 f.SetMemberIsUsed ();
2965 if (FieldInfo.IsStatic){
2967 ig.Emit (OpCodes.Volatile);
2969 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2972 EmitInstance (ec, false);
2975 ig.Emit (OpCodes.Volatile);
2977 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
2980 ig.Emit (OpCodes.Ldflda, FieldInfo);
2981 ig.Emit (OpCodes.Ldflda, ff.Element);
2984 ig.Emit (OpCodes.Ldfld, FieldInfo);
2989 ec.ig.Emit (OpCodes.Dup);
2990 if (!FieldInfo.IsStatic) {
2991 temp = new LocalTemporary (ec, this.Type);
2997 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
2999 FieldAttributes fa = FieldInfo.Attributes;
3000 bool is_static = (fa & FieldAttributes.Static) != 0;
3001 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3002 ILGenerator ig = ec.ig;
3003 prepared = prepare_for_load;
3005 if (is_readonly && !ec.IsConstructor){
3006 Report_AssignToReadonly (source);
3010 EmitInstance (ec, prepare_for_load);
3014 ec.ig.Emit (OpCodes.Dup);
3015 if (!FieldInfo.IsStatic) {
3016 temp = new LocalTemporary (ec, this.Type);
3021 if (FieldInfo is FieldBuilder){
3022 FieldBase f = TypeManager.GetField (FieldInfo);
3024 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3025 ig.Emit (OpCodes.Volatile);
3032 ig.Emit (OpCodes.Stsfld, FieldInfo);
3034 ig.Emit (OpCodes.Stfld, FieldInfo);
3040 public override void Emit (EmitContext ec)
3045 public void AddressOf (EmitContext ec, AddressOp mode)
3047 ILGenerator ig = ec.ig;
3049 if (FieldInfo is FieldBuilder){
3050 FieldBase f = TypeManager.GetField (FieldInfo);
3052 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3053 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3054 f.GetSignatureForError ());
3058 if ((mode & AddressOp.Store) != 0)
3060 if ((mode & AddressOp.Load) != 0)
3061 f.SetMemberIsUsed ();
3066 // Handle initonly fields specially: make a copy and then
3067 // get the address of the copy.
3070 if (FieldInfo.IsInitOnly){
3072 if (ec.IsConstructor){
3073 if (FieldInfo.IsStatic){
3085 local = ig.DeclareLocal (type);
3086 ig.Emit (OpCodes.Stloc, local);
3087 ig.Emit (OpCodes.Ldloca, local);
3092 if (FieldInfo.IsStatic){
3093 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3095 EmitInstance (ec, false);
3096 ig.Emit (OpCodes.Ldflda, FieldInfo);
3102 // A FieldExpr whose address can not be taken
3104 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3105 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3109 public new void AddressOf (EmitContext ec, AddressOp mode)
3111 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3116 /// Expression that evaluates to a Property. The Assign class
3117 /// might set the `Value' expression if we are in an assignment.
3119 /// This is not an LValue because we need to re-write the expression, we
3120 /// can not take data from the stack and store it.
3122 public class PropertyExpr : MemberExpr, IAssignMethod {
3123 public readonly PropertyInfo PropertyInfo;
3126 // This is set externally by the `BaseAccess' class
3129 MethodInfo getter, setter;
3134 LocalTemporary temp;
3137 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3139 public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
3142 eclass = ExprClass.PropertyAccess;
3146 type = TypeManager.TypeToCoreType (pi.PropertyType);
3148 ResolveAccessors (containerType);
3151 public override string Name {
3153 return PropertyInfo.Name;
3157 public override bool IsInstance {
3163 public override bool IsStatic {
3169 public override Type DeclaringType {
3171 return PropertyInfo.DeclaringType;
3175 public override string GetSignatureForError ()
3177 return TypeManager.GetFullNameSignature (PropertyInfo);
3180 void FindAccessors (Type invocation_type)
3182 const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3183 BindingFlags.Static | BindingFlags.Instance |
3184 BindingFlags.DeclaredOnly;
3186 Type current = PropertyInfo.DeclaringType;
3187 for (; current != null; current = current.BaseType) {
3188 MemberInfo[] group = TypeManager.MemberLookup (
3189 invocation_type, invocation_type, current,
3190 MemberTypes.Property, flags, PropertyInfo.Name, null);
3195 if (group.Length != 1)
3196 // Oooops, can this ever happen ?
3199 PropertyInfo pi = (PropertyInfo) group [0];
3202 getter = pi.GetGetMethod (true);
3205 setter = pi.GetSetMethod (true);
3207 MethodInfo accessor = getter != null ? getter : setter;
3209 if (!accessor.IsVirtual)
3215 // We also perform the permission checking here, as the PropertyInfo does not
3216 // hold the information for the accessibility of its setter/getter
3218 // TODO: can use TypeManager.GetProperty to boost performance
3219 void ResolveAccessors (Type containerType)
3221 FindAccessors (containerType);
3223 if (getter != null) {
3224 IMethodData md = TypeManager.GetMethod (getter);
3226 md.SetMemberIsUsed ();
3228 AccessorTable [getter] = PropertyInfo;
3229 is_static = getter.IsStatic;
3232 if (setter != null) {
3233 IMethodData md = TypeManager.GetMethod (setter);
3235 md.SetMemberIsUsed ();
3237 AccessorTable [setter] = PropertyInfo;
3238 is_static = setter.IsStatic;
3242 bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
3245 InstanceExpression = null;
3249 if (InstanceExpression == null) {
3250 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3254 if (lvalue_instance)
3255 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3257 InstanceExpression = InstanceExpression.DoResolve (ec);
3258 if (InstanceExpression == null)
3261 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3263 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3264 InstanceExpression.Type != ec.ContainerType &&
3265 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3266 !InstanceExpression.Type.IsSubclassOf (ec.ContainerType)) {
3267 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3274 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3276 // TODO: correctly we should compare arguments but it will lead to bigger changes
3277 if (mi is MethodBuilder) {
3278 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3282 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3284 ParameterData iparams = TypeManager.GetParameterData (mi);
3285 sig.Append (getter ? "get_" : "set_");
3287 sig.Append (iparams.GetSignatureForError ());
3289 Report.SymbolRelatedToPreviousError (mi);
3290 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3291 Name, sig.ToString ());
3294 override public Expression DoResolve (EmitContext ec)
3299 if (getter != null){
3300 if (TypeManager.GetParameterData (getter).Count != 0){
3301 Error_PropertyNotFound (getter, true);
3306 if (getter == null){
3308 // The following condition happens if the PropertyExpr was
3309 // created, but is invalid (ie, the property is inaccessible),
3310 // and we did not want to embed the knowledge about this in
3311 // the caller routine. This only avoids double error reporting.
3316 if (InstanceExpression != EmptyExpression.Null) {
3317 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3318 TypeManager.GetFullNameSignature (PropertyInfo));
3323 bool must_do_cs1540_check = false;
3324 if (getter != null &&
3325 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3326 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3327 if (pm != null && pm.HasCustomAccessModifier) {
3328 Report.SymbolRelatedToPreviousError (pm);
3329 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3330 TypeManager.CSharpSignature (getter));
3333 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3337 if (!InstanceResolve (ec, false, must_do_cs1540_check))
3341 // Only base will allow this invocation to happen.
3343 if (IsBase && getter.IsAbstract) {
3344 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3348 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3358 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3360 if (right_side == EmptyExpression.OutAccess) {
3361 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
3362 GetSignatureForError ());
3366 if (right_side == EmptyExpression.LValueMemberAccess) {
3367 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
3368 GetSignatureForError ());
3372 if (setter == null){
3374 // The following condition happens if the PropertyExpr was
3375 // created, but is invalid (ie, the property is inaccessible),
3376 // and we did not want to embed the knowledge about this in
3377 // the caller routine. This only avoids double error reporting.
3381 Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
3382 GetSignatureForError ());
3386 if (TypeManager.GetParameterData (setter).Count != 1){
3387 Error_PropertyNotFound (setter, false);
3391 bool must_do_cs1540_check;
3392 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3393 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3394 if (pm != null && pm.HasCustomAccessModifier) {
3395 Report.SymbolRelatedToPreviousError (pm);
3396 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3397 TypeManager.CSharpSignature (setter));
3400 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3404 if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
3408 // Only base will allow this invocation to happen.
3410 if (IsBase && setter.IsAbstract){
3411 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3418 public override void Emit (EmitContext ec)
3423 public void Emit (EmitContext ec, bool leave_copy)
3426 // Special case: length of single dimension array property is turned into ldlen
3428 if ((getter == TypeManager.system_int_array_get_length) ||
3429 (getter == TypeManager.int_array_get_length)){
3430 Type iet = InstanceExpression.Type;
3433 // System.Array.Length can be called, but the Type does not
3434 // support invoking GetArrayRank, so test for that case first
3436 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3438 EmitInstance (ec, false);
3439 ec.ig.Emit (OpCodes.Ldlen);
3440 ec.ig.Emit (OpCodes.Conv_I4);
3445 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3448 ec.ig.Emit (OpCodes.Dup);
3450 temp = new LocalTemporary (ec, this.Type);
3457 // Implements the IAssignMethod interface for assignments
3459 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3461 Expression my_source = source;
3463 prepared = prepare_for_load;
3468 ec.ig.Emit (OpCodes.Dup);
3470 temp = new LocalTemporary (ec, this.Type);
3474 } else if (leave_copy) {
3477 temp = new LocalTemporary (ec, this.Type);
3483 ArrayList args = new ArrayList (1);
3484 args.Add (new Argument (my_source, Argument.AType.Expression));
3486 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3494 /// Fully resolved expression that evaluates to an Event
3496 public class EventExpr : MemberExpr {
3497 public readonly EventInfo EventInfo;
3500 MethodInfo add_accessor, remove_accessor;
3502 public EventExpr (EventInfo ei, Location loc)
3506 eclass = ExprClass.EventAccess;
3508 add_accessor = TypeManager.GetAddMethod (ei);
3509 remove_accessor = TypeManager.GetRemoveMethod (ei);
3511 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3514 if (EventInfo is MyEventBuilder){
3515 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3516 type = eb.EventType;
3519 type = EventInfo.EventHandlerType;
3522 public override string Name {
3524 return EventInfo.Name;
3528 public override bool IsInstance {
3534 public override bool IsStatic {
3540 public override Type DeclaringType {
3542 return EventInfo.DeclaringType;
3546 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3547 SimpleName original)
3550 // If the event is local to this class, we transform ourselves into a FieldExpr
3553 if (EventInfo.DeclaringType == ec.ContainerType ||
3554 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3555 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3558 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
3561 Report.Error (-200, loc, "Internal error!!");
3565 InstanceExpression = null;
3567 return ml.ResolveMemberAccess (ec, left, loc, original);
3571 return base.ResolveMemberAccess (ec, left, loc, original);
3575 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3578 InstanceExpression = null;
3582 if (InstanceExpression == null) {
3583 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3587 InstanceExpression = InstanceExpression.DoResolve (ec);
3588 if (InstanceExpression == null)
3592 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3593 // However, in the Event case, we reported a CS0122 instead.
3595 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3596 InstanceExpression.Type != ec.ContainerType &&
3597 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3598 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3605 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3607 return DoResolve (ec);
3610 public override Expression DoResolve (EmitContext ec)
3612 bool must_do_cs1540_check;
3613 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3614 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3615 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3619 if (!InstanceResolve (ec, must_do_cs1540_check))
3625 public override void Emit (EmitContext ec)
3627 if (InstanceExpression is This)
3628 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3630 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3631 "(except on the defining type)", Name);
3634 public override string GetSignatureForError ()
3636 return TypeManager.CSharpSignature (EventInfo);
3639 public void EmitAddOrRemove (EmitContext ec, Expression source)
3641 BinaryDelegate source_del = (BinaryDelegate) source;
3642 Expression handler = source_del.Right;
3644 Argument arg = new Argument (handler, Argument.AType.Expression);
3645 ArrayList args = new ArrayList ();
3649 if (source_del.IsAddition)
3650 Invocation.EmitCall (
3651 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3653 Invocation.EmitCall (
3654 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3659 public class TemporaryVariable : Expression, IMemoryLocation
3663 public TemporaryVariable (Type type, Location loc)
3667 eclass = ExprClass.Value;
3670 public override Expression DoResolve (EmitContext ec)
3675 TypeExpr te = new TypeExpression (type, loc);
3676 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3677 if (!li.Resolve (ec))
3680 AnonymousContainer am = ec.CurrentAnonymousMethod;
3681 if ((am != null) && am.IsIterator)
3682 ec.CaptureVariable (li);
3687 public override void Emit (EmitContext ec)
3689 ILGenerator ig = ec.ig;
3691 if (li.FieldBuilder != null) {
3692 ig.Emit (OpCodes.Ldarg_0);
3693 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3695 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3699 public void EmitLoadAddress (EmitContext ec)
3701 ILGenerator ig = ec.ig;
3703 if (li.FieldBuilder != null) {
3704 ig.Emit (OpCodes.Ldarg_0);
3705 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3707 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3711 public void Store (EmitContext ec, Expression right_side)
3713 if (li.FieldBuilder != null)
3714 ec.ig.Emit (OpCodes.Ldarg_0);
3716 right_side.Emit (ec);
3717 if (li.FieldBuilder != null) {
3718 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3720 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3724 public void EmitThis (EmitContext ec)
3726 if (li.FieldBuilder != null) {
3727 ec.ig.Emit (OpCodes.Ldarg_0);
3731 public void EmitStore (ILGenerator ig)
3733 if (li.FieldBuilder != null)
3734 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3736 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3739 public void AddressOf (EmitContext ec, AddressOp mode)
3741 EmitLoadAddress (ec);