2 // ecore.cs: Core of the Expression representation for the intermediate tree.
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2001, 2002, 2003 Ximian, Inc.
11 namespace Mono.CSharp {
13 using System.Collections;
14 using System.Diagnostics;
15 using System.Reflection;
16 using System.Reflection.Emit;
20 /// The ExprClass class contains the is used to pass the
21 /// classification of an expression (value, variable, namespace,
22 /// type, method group, property access, event access, indexer access,
25 public enum ExprClass : byte {
40 /// This is used to tell Resolve in which types of expressions we're
44 public enum ResolveFlags {
45 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
48 // Returns a type expression.
51 // Returns a method group.
54 // Mask of all the expression class flags.
57 // Disable control flow analysis while resolving the expression.
58 // This is used when resolving the instance expression of a field expression.
59 DisableFlowAnalysis = 8,
61 // Set if this is resolving the first part of a MemberAccess.
64 // Disable control flow analysis _of struct_ while resolving the expression.
65 // This is used when resolving the instance expression of a field expression.
66 DisableStructFlowAnalysis = 32,
71 // This is just as a hint to AddressOf of what will be done with the
74 public enum AddressOp {
81 /// This interface is implemented by variables
83 public interface IMemoryLocation {
85 /// The AddressOf method should generate code that loads
86 /// the address of the object and leaves it on the stack.
88 /// The `mode' argument is used to notify the expression
89 /// of whether this will be used to read from the address or
90 /// write to the address.
92 /// This is just a hint that can be used to provide good error
93 /// reporting, and should have no other side effects.
95 void AddressOf (EmitContext ec, AddressOp mode);
99 /// This interface is implemented by variables
101 public interface IVariable {
102 VariableInfo VariableInfo {
110 /// Base class for expressions
112 public abstract class Expression {
113 public ExprClass eclass;
115 protected Location loc;
119 set { type = value; }
122 public virtual Location Location {
127 /// Utility wrapper routine for Error, just to beautify the code
129 public void Error (int error, string s)
132 Report.Error (error, s);
134 Report.Error (error, loc, s);
137 // Not nice but we have broken hierarchy
138 public virtual void CheckMarshallByRefAccess (Type container) {}
140 public virtual string GetSignatureForError ()
142 return TypeManager.CSharpName (type);
145 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
147 MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
149 must_do_cs1540_check = false; // by default we do not check for this
151 if (ma == MethodAttributes.Public)
155 // If only accessible to the current class or children
157 if (ma == MethodAttributes.Private)
158 return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
159 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
161 if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
162 TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
163 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
166 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
170 // Family and FamANDAssem require that we derive.
171 // FamORAssem requires that we derive if in different assemblies.
172 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
175 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
176 must_do_cs1540_check = true;
182 /// Performs semantic analysis on the Expression
186 /// The Resolve method is invoked to perform the semantic analysis
189 /// The return value is an expression (it can be the
190 /// same expression in some cases) or a new
191 /// expression that better represents this node.
193 /// For example, optimizations of Unary (LiteralInt)
194 /// would return a new LiteralInt with a negated
197 /// If there is an error during semantic analysis,
198 /// then an error should be reported (using Report)
199 /// and a null value should be returned.
201 /// There are two side effects expected from calling
202 /// Resolve(): the the field variable "eclass" should
203 /// be set to any value of the enumeration
204 /// `ExprClass' and the type variable should be set
205 /// to a valid type (this is the type of the
208 public abstract Expression DoResolve (EmitContext ec);
210 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
216 // This is used if the expression should be resolved as a type or namespace name.
217 // the default implementation fails.
219 public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
225 // This is used to resolve the expression as a type, a null
226 // value will be returned if the expression is not a type
229 public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
231 int errors = Report.Errors;
233 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
236 if (!silent && errors == Report.Errors)
237 Report.Error (118, loc, "Expecting a type.");
241 if (fne.eclass != ExprClass.Type) {
242 if (!silent && errors == Report.Errors)
243 fne.Error_UnexpectedKind (null, "type", loc);
247 TypeExpr te = fne as TypeExpr;
249 if (!te.CheckAccessLevel (ec.DeclContainer)) {
250 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
254 // Constrains don't need to be checked for overrides
255 GenericMethod gm = ec.DeclContainer as GenericMethod;
256 if (gm != null && (gm.ModFlags & Modifiers.OVERRIDE) != 0) {
261 ConstructedType ct = te as ConstructedType;
262 if ((ct != null) && !ct.CheckConstraints (ec))
269 public static void ErrorIsInaccesible (Location loc, string name)
271 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
274 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
276 Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
277 + " the qualifier must be of type `{2}' (or derived from it)",
278 TypeManager.GetFullNameSignature (m),
279 TypeManager.CSharpName (qualifier),
280 TypeManager.CSharpName (container));
284 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
286 if (Type.Name == target.Name){
287 Report.ExtraInformation (loc,
289 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
290 Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
295 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
296 GetSignatureForError (), TypeManager.CSharpName (target));
300 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
301 bool b = Convert.ExplicitNumericConversion (e, target) != null;
303 if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
304 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
305 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
309 if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
310 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
311 GetSignatureForError (), TypeManager.CSharpName (target));
315 Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
316 Type == TypeManager.anonymous_method_type ?
317 "anonymous method" : "`" + GetSignatureForError () + "'",
318 TypeManager.CSharpName (target));
321 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
323 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
324 TypeManager.CSharpName (type), name);
327 ResolveFlags ExprClassToResolveFlags ()
331 case ExprClass.Namespace:
332 return ResolveFlags.Type;
334 case ExprClass.MethodGroup:
335 return ResolveFlags.MethodGroup;
337 case ExprClass.Value:
338 case ExprClass.Variable:
339 case ExprClass.PropertyAccess:
340 case ExprClass.EventAccess:
341 case ExprClass.IndexerAccess:
342 return ResolveFlags.VariableOrValue;
345 throw new Exception ("Expression " + GetType () +
346 " ExprClass is Invalid after resolve");
352 /// Resolves an expression and performs semantic analysis on it.
356 /// Currently Resolve wraps DoResolve to perform sanity
357 /// checking and assertion checking on what we expect from Resolve.
359 public Expression Resolve (EmitContext ec, ResolveFlags flags)
361 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
362 return ResolveAsTypeStep (ec, false);
364 bool old_do_flow_analysis = ec.DoFlowAnalysis;
365 bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;
366 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
367 ec.DoFlowAnalysis = false;
368 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
369 ec.OmitStructFlowAnalysis = true;
372 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
373 if (this is SimpleName)
374 e = ((SimpleName) this).DoResolve (ec, intermediate);
379 ec.DoFlowAnalysis = old_do_flow_analysis;
380 ec.OmitStructFlowAnalysis = old_omit_struct_analysis;
385 if ((flags & e.ExprClassToResolveFlags ()) == 0) {
386 e.Error_UnexpectedKind (flags, loc);
390 if (e.type == null && !(e is Namespace)) {
391 throw new Exception (
392 "Expression " + e.GetType () +
393 " did not set its type after Resolve\n" +
394 "called from: " + this.GetType ());
401 /// Resolves an expression and performs semantic analysis on it.
403 public Expression Resolve (EmitContext ec)
405 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
407 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
408 ((MethodGroupExpr) e).ReportUsageError ();
414 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
416 Expression e = Resolve (ec);
420 Constant c = e as Constant;
424 EmptyCast empty = e as EmptyCast;
426 c = empty.Child as Constant;
428 // TODO: not sure about this maybe there is easier way how to use EmptyCast
435 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
440 /// Resolves an expression for LValue assignment
444 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
445 /// checking and assertion checking on what we expect from Resolve
447 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
449 int errors = Report.Errors;
450 Expression e = DoResolveLValue (ec, right_side);
453 if (errors == Report.Errors)
454 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
459 if (e.eclass == ExprClass.Invalid)
460 throw new Exception ("Expression " + e +
461 " ExprClass is Invalid after resolve");
463 if (e.eclass == ExprClass.MethodGroup) {
464 ((MethodGroupExpr) e).ReportUsageError ();
468 if ((e.type == null) && !(e is ConstructedType))
469 throw new Exception ("Expression " + e +
470 " did not set its type after Resolve");
477 /// Emits the code for the expression
481 /// The Emit method is invoked to generate the code
482 /// for the expression.
484 public abstract void Emit (EmitContext ec);
486 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
489 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
493 /// Protected constructor. Only derivate types should
494 /// be able to be created
497 protected Expression ()
499 eclass = ExprClass.Invalid;
504 /// Returns a literalized version of a literal FieldInfo
508 /// The possible return values are:
509 /// IntConstant, UIntConstant
510 /// LongLiteral, ULongConstant
511 /// FloatConstant, DoubleConstant
514 /// The value returned is already resolved.
516 public static Constant Constantify (object v, Type t)
518 if (t == TypeManager.int32_type)
519 return new IntConstant ((int) v, Location.Null);
520 else if (t == TypeManager.uint32_type)
521 return new UIntConstant ((uint) v, Location.Null);
522 else if (t == TypeManager.int64_type)
523 return new LongConstant ((long) v, Location.Null);
524 else if (t == TypeManager.uint64_type)
525 return new ULongConstant ((ulong) v, Location.Null);
526 else if (t == TypeManager.float_type)
527 return new FloatConstant ((float) v, Location.Null);
528 else if (t == TypeManager.double_type)
529 return new DoubleConstant ((double) v, Location.Null);
530 else if (t == TypeManager.string_type)
531 return new StringConstant ((string) v, Location.Null);
532 else if (t == TypeManager.short_type)
533 return new ShortConstant ((short)v, Location.Null);
534 else if (t == TypeManager.ushort_type)
535 return new UShortConstant ((ushort)v, Location.Null);
536 else if (t == TypeManager.sbyte_type)
537 return new SByteConstant ((sbyte)v, Location.Null);
538 else if (t == TypeManager.byte_type)
539 return new ByteConstant ((byte)v, Location.Null);
540 else if (t == TypeManager.char_type)
541 return new CharConstant ((char)v, Location.Null);
542 else if (t == TypeManager.bool_type)
543 return new BoolConstant ((bool) v, Location.Null);
544 else if (t == TypeManager.decimal_type)
545 return new DecimalConstant ((decimal) v, Location.Null);
546 else if (TypeManager.IsEnumType (t)){
547 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
549 real_type = System.Enum.GetUnderlyingType (real_type);
551 Constant e = Constantify (v, real_type);
553 return new EnumConstant (e, t);
554 } else if (v == null && !TypeManager.IsValueType (t))
555 return new NullLiteral (Location.Null);
557 throw new Exception ("Unknown type for constant (" + t +
562 /// Returns a fully formed expression after a MemberLookup
565 public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
568 return new EventExpr ((EventInfo) mi, loc);
569 else if (mi is FieldInfo)
570 return new FieldExpr ((FieldInfo) mi, loc);
571 else if (mi is PropertyInfo)
572 return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
573 else if (mi is Type){
574 return new TypeExpression ((System.Type) mi, loc);
580 protected static ArrayList almostMatchedMembers = new ArrayList (4);
583 // FIXME: Probably implement a cache for (t,name,current_access_set)?
585 // This code could use some optimizations, but we need to do some
586 // measurements. For example, we could use a delegate to `flag' when
587 // something can not any longer be a method-group (because it is something
591 // If the return value is an Array, then it is an array of
594 // If the return value is an MemberInfo, it is anything, but a Method
598 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
599 // the arguments here and have MemberLookup return only the methods that
600 // match the argument count/type, unlike we are doing now (we delay this
603 // This is so we can catch correctly attempts to invoke instance methods
604 // from a static body (scan for error 120 in ResolveSimpleName).
607 // FIXME: Potential optimization, have a static ArrayList
610 public static Expression MemberLookup (Type container_type, Type queried_type, string name,
611 MemberTypes mt, BindingFlags bf, Location loc)
613 return MemberLookup (container_type, null, queried_type, name, mt, bf, loc);
617 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
618 // `qualifier_type' or null to lookup members in the current class.
621 public static Expression MemberLookup (Type container_type,
622 Type qualifier_type, Type queried_type,
623 string name, MemberTypes mt,
624 BindingFlags bf, Location loc)
626 almostMatchedMembers.Clear ();
628 MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
629 queried_type, mt, bf, name, almostMatchedMembers);
634 int count = mi.Length;
636 if (mi [0] is MethodBase)
637 return new MethodGroupExpr (mi, loc);
642 return ExprClassFromMemberInfo (container_type, mi [0], loc);
645 public const MemberTypes AllMemberTypes =
646 MemberTypes.Constructor |
650 MemberTypes.NestedType |
651 MemberTypes.Property;
653 public const BindingFlags AllBindingFlags =
654 BindingFlags.Public |
655 BindingFlags.Static |
656 BindingFlags.Instance;
658 public static Expression MemberLookup (EmitContext ec, Type queried_type,
659 string name, Location loc)
661 return MemberLookup (ec.ContainerType, null, queried_type, name,
662 AllMemberTypes, AllBindingFlags, loc);
665 public static Expression MemberLookup (Type container_type, Type qualifier_type,
666 Type queried_type, string name, Location loc)
668 return MemberLookup (container_type, qualifier_type, queried_type,
669 name, AllMemberTypes, AllBindingFlags, loc);
672 public static Expression MethodLookup (EmitContext ec, Type queried_type,
673 string name, Location loc)
675 return MemberLookup (ec.ContainerType, null, queried_type, name,
676 MemberTypes.Method, AllBindingFlags, loc);
680 /// This is a wrapper for MemberLookup that is not used to "probe", but
681 /// to find a final definition. If the final definition is not found, we
682 /// look for private members and display a useful debugging message if we
685 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
686 Type queried_type, string name, Location loc)
688 return MemberLookupFinal (ec, qualifier_type, queried_type, name,
689 AllMemberTypes, AllBindingFlags, loc);
692 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
693 Type queried_type, string name,
694 MemberTypes mt, BindingFlags bf,
699 int errors = Report.Errors;
701 e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
703 if (e == null && errors == Report.Errors)
704 // No errors were reported by MemberLookup, but there was an error.
705 MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
710 public static void MemberLookupFailed (Type container_type, Type qualifier_type,
711 Type queried_type, string name,
712 string class_name, bool complain_if_none_found,
715 if (almostMatchedMembers.Count != 0) {
716 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
717 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
718 for (int j = 0; j < i; ++j) {
719 if (m == almostMatchedMembers [j]) {
727 Type declaring_type = m.DeclaringType;
729 Report.SymbolRelatedToPreviousError (m);
730 if (qualifier_type == null) {
731 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
732 TypeManager.CSharpName (m.DeclaringType),
733 TypeManager.CSharpName (container_type));
735 } else if (qualifier_type != container_type &&
736 TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) {
737 // Although a derived class can access protected members of
738 // its base class it cannot do so through an instance of the
739 // base class (CS1540). If the qualifier_type is a base of the
740 // ec.ContainerType and the lookup succeeds with the latter one,
741 // then we are in this situation.
742 Error_CannotAccessProtected (loc, m, qualifier_type, container_type);
744 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
747 almostMatchedMembers.Clear ();
751 MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
752 AllMemberTypes, AllBindingFlags |
753 BindingFlags.NonPublic, name, null);
755 if (lookup == null) {
756 if (!complain_if_none_found)
759 if (class_name != null)
760 Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
763 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
767 if (TypeManager.MemberLookup (queried_type, null, queried_type,
768 AllMemberTypes, AllBindingFlags |
769 BindingFlags.NonPublic, name, null) == null) {
770 if ((lookup.Length == 1) && (lookup [0] is Type)) {
771 Type t = (Type) lookup [0];
773 Report.Error (305, loc,
774 "Using the generic type `{0}' " +
775 "requires {1} type arguments",
776 TypeManager.CSharpName (t),
777 TypeManager.GetNumberOfTypeArguments (t).ToString ());
782 MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
783 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
784 if (name == ".ctor" && ml.Count == 0)
786 Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
790 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
794 /// Returns an expression that can be used to invoke operator true
795 /// on the expression if it exists.
797 static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
799 return GetOperatorTrueOrFalse (ec, e, true, loc);
803 /// Returns an expression that can be used to invoke operator false
804 /// on the expression if it exists.
806 static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
808 return GetOperatorTrueOrFalse (ec, e, false, loc);
811 static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
814 Expression operator_group;
816 if (TypeManager.IsNullableType (e.Type))
817 return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
819 operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
820 if (operator_group == null)
823 ArrayList arguments = new ArrayList ();
824 arguments.Add (new Argument (e, Argument.AType.Expression));
825 method = Invocation.OverloadResolve (
826 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
831 return new StaticCallExpr ((MethodInfo) method, arguments, loc);
835 /// Resolves the expression `e' into a boolean expression: either through
836 /// an implicit conversion, or through an `operator true' invocation
838 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
844 if (e.Type == TypeManager.bool_type)
847 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
849 if (converted != null)
853 // If no implicit conversion to bool exists, try using `operator true'
855 converted = Expression.GetOperatorTrue (ec, e, loc);
856 if (converted == null){
857 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
863 public virtual string ExprClassName
867 case ExprClass.Invalid:
869 case ExprClass.Value:
871 case ExprClass.Variable:
873 case ExprClass.Namespace:
877 case ExprClass.MethodGroup:
878 return "method group";
879 case ExprClass.PropertyAccess:
880 return "property access";
881 case ExprClass.EventAccess:
882 return "event access";
883 case ExprClass.IndexerAccess:
884 return "indexer access";
885 case ExprClass.Nothing:
888 throw new Exception ("Should not happen");
893 /// Reports that we were expecting `expr' to be of class `expected'
895 public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
897 Error_UnexpectedKind (ds, expected, ExprClassName, loc);
900 public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
902 string name = GetSignatureForError ();
904 name = ds.GetSignatureForError () + '.' + name;
906 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
907 name, was, expected);
910 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
912 string [] valid = new string [4];
915 if ((flags & ResolveFlags.VariableOrValue) != 0) {
916 valid [count++] = "variable";
917 valid [count++] = "value";
920 if ((flags & ResolveFlags.Type) != 0)
921 valid [count++] = "type";
923 if ((flags & ResolveFlags.MethodGroup) != 0)
924 valid [count++] = "method group";
927 valid [count++] = "unknown";
929 StringBuilder sb = new StringBuilder (valid [0]);
930 for (int i = 1; i < count - 1; i++) {
932 sb.Append (valid [i]);
935 sb.Append ("' or `");
936 sb.Append (valid [count - 1]);
939 Report.Error (119, loc,
940 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
943 public static void UnsafeError (Location loc)
945 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
949 // Load the object from the pointer.
951 public static void LoadFromPtr (ILGenerator ig, Type t)
953 if (t == TypeManager.int32_type)
954 ig.Emit (OpCodes.Ldind_I4);
955 else if (t == TypeManager.uint32_type)
956 ig.Emit (OpCodes.Ldind_U4);
957 else if (t == TypeManager.short_type)
958 ig.Emit (OpCodes.Ldind_I2);
959 else if (t == TypeManager.ushort_type)
960 ig.Emit (OpCodes.Ldind_U2);
961 else if (t == TypeManager.char_type)
962 ig.Emit (OpCodes.Ldind_U2);
963 else if (t == TypeManager.byte_type)
964 ig.Emit (OpCodes.Ldind_U1);
965 else if (t == TypeManager.sbyte_type)
966 ig.Emit (OpCodes.Ldind_I1);
967 else if (t == TypeManager.uint64_type)
968 ig.Emit (OpCodes.Ldind_I8);
969 else if (t == TypeManager.int64_type)
970 ig.Emit (OpCodes.Ldind_I8);
971 else if (t == TypeManager.float_type)
972 ig.Emit (OpCodes.Ldind_R4);
973 else if (t == TypeManager.double_type)
974 ig.Emit (OpCodes.Ldind_R8);
975 else if (t == TypeManager.bool_type)
976 ig.Emit (OpCodes.Ldind_I1);
977 else if (t == TypeManager.intptr_type)
978 ig.Emit (OpCodes.Ldind_I);
979 else if (TypeManager.IsEnumType (t)) {
980 if (t == TypeManager.enum_type)
981 ig.Emit (OpCodes.Ldind_Ref);
983 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
984 } else if (t.IsValueType || t.IsGenericParameter)
985 ig.Emit (OpCodes.Ldobj, t);
986 else if (t.IsPointer)
987 ig.Emit (OpCodes.Ldind_I);
989 ig.Emit (OpCodes.Ldind_Ref);
993 // The stack contains the pointer and the value of type `type'
995 public static void StoreFromPtr (ILGenerator ig, Type type)
997 if (TypeManager.IsEnumType (type))
998 type = TypeManager.EnumToUnderlying (type);
999 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
1000 ig.Emit (OpCodes.Stind_I4);
1001 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
1002 ig.Emit (OpCodes.Stind_I8);
1003 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
1004 type == TypeManager.ushort_type)
1005 ig.Emit (OpCodes.Stind_I2);
1006 else if (type == TypeManager.float_type)
1007 ig.Emit (OpCodes.Stind_R4);
1008 else if (type == TypeManager.double_type)
1009 ig.Emit (OpCodes.Stind_R8);
1010 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1011 type == TypeManager.bool_type)
1012 ig.Emit (OpCodes.Stind_I1);
1013 else if (type == TypeManager.intptr_type)
1014 ig.Emit (OpCodes.Stind_I);
1015 else if (type.IsValueType || type.IsGenericParameter)
1016 ig.Emit (OpCodes.Stobj, type);
1018 ig.Emit (OpCodes.Stind_Ref);
1022 // Returns the size of type `t' if known, otherwise, 0
1024 public static int GetTypeSize (Type t)
1026 t = TypeManager.TypeToCoreType (t);
1027 if (t == TypeManager.int32_type ||
1028 t == TypeManager.uint32_type ||
1029 t == TypeManager.float_type)
1031 else if (t == TypeManager.int64_type ||
1032 t == TypeManager.uint64_type ||
1033 t == TypeManager.double_type)
1035 else if (t == TypeManager.byte_type ||
1036 t == TypeManager.sbyte_type ||
1037 t == TypeManager.bool_type)
1039 else if (t == TypeManager.short_type ||
1040 t == TypeManager.char_type ||
1041 t == TypeManager.ushort_type)
1043 else if (t == TypeManager.decimal_type)
1049 public static void Error_NegativeArrayIndex (Location loc)
1051 Report.Error (248, loc, "Cannot create an array with a negative size");
1054 protected void Error_CannotCallAbstractBase (string name)
1056 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1060 // Converts `source' to an int, uint, long or ulong.
1062 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1066 bool old_checked = ec.CheckState;
1067 ec.CheckState = true;
1069 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1070 if (target == null){
1071 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1072 if (target == null){
1073 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1074 if (target == null){
1075 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1077 source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1081 ec.CheckState = old_checked;
1084 // Only positive constants are allowed at compile time
1086 if (target is Constant){
1087 if (target is IntConstant){
1088 if (((IntConstant) target).Value < 0){
1089 Error_NegativeArrayIndex (loc);
1094 if (target is LongConstant){
1095 if (((LongConstant) target).Value < 0){
1096 Error_NegativeArrayIndex (loc);
1109 /// This is just a base class for expressions that can
1110 /// appear on statements (invocations, object creation,
1111 /// assignments, post/pre increment and decrement). The idea
1112 /// being that they would support an extra Emition interface that
1113 /// does not leave a result on the stack.
1115 public abstract class ExpressionStatement : Expression {
1117 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1119 Expression e = Resolve (ec);
1123 ExpressionStatement es = e as ExpressionStatement;
1125 Error (201, "Only assignment, call, increment, decrement and new object " +
1126 "expressions can be used as a statement");
1132 /// Requests the expression to be emitted in a `statement'
1133 /// context. This means that no new value is left on the
1134 /// stack after invoking this method (constrasted with
1135 /// Emit that will always leave a value on the stack).
1137 public abstract void EmitStatement (EmitContext ec);
1141 /// This kind of cast is used to encapsulate the child
1142 /// whose type is child.Type into an expression that is
1143 /// reported to return "return_type". This is used to encapsulate
1144 /// expressions which have compatible types, but need to be dealt
1145 /// at higher levels with.
1147 /// For example, a "byte" expression could be encapsulated in one
1148 /// of these as an "unsigned int". The type for the expression
1149 /// would be "unsigned int".
1152 public class EmptyCast : Expression {
1153 protected Expression child;
1155 public Expression Child {
1161 public EmptyCast (Expression child, Type return_type)
1163 eclass = child.eclass;
1164 loc = child.Location;
1169 public override Expression DoResolve (EmitContext ec)
1171 // This should never be invoked, we are born in fully
1172 // initialized state.
1177 public override void Emit (EmitContext ec)
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 if (t.IsGenericParameter)
1531 ig.Emit (OpCodes.Unbox_Any, t);
1533 ig.Emit (OpCodes.Unbox, t);
1535 LoadFromPtr (ig, t);
1541 /// This is used to perform explicit numeric conversions.
1543 /// Explicit numeric conversions might trigger exceptions in a checked
1544 /// context, so they should generate the conv.ovf opcodes instead of
1547 public class ConvCast : EmptyCast {
1548 public enum Mode : byte {
1549 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1551 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1552 U2_I1, U2_U1, U2_I2, U2_CH,
1553 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1554 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1555 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1556 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1557 CH_I1, CH_U1, CH_I2,
1558 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1559 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1564 public ConvCast (Expression child, Type return_type, Mode m)
1565 : base (child, return_type)
1570 public override Expression DoResolve (EmitContext ec)
1572 // This should never be invoked, we are born in fully
1573 // initialized state.
1578 public override string ToString ()
1580 return String.Format ("ConvCast ({0}, {1})", mode, child);
1583 public override void Emit (EmitContext ec)
1585 ILGenerator ig = ec.ig;
1591 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1592 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1593 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1594 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1595 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1597 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1598 case Mode.U1_CH: /* nothing */ break;
1600 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1601 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1602 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1603 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1604 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1605 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1607 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1608 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1609 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1610 case Mode.U2_CH: /* nothing */ break;
1612 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1613 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1614 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1615 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1616 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1617 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1618 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1620 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1621 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1622 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1623 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1624 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1625 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1627 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1628 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1629 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1630 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1631 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1632 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1633 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1634 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1636 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1637 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1638 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1639 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1640 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1641 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1642 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1643 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1645 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1646 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1647 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1649 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1650 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1651 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1652 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1653 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1654 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1655 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1656 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1657 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1659 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1660 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1661 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1662 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1663 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1664 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1665 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1666 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1667 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1668 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1672 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1673 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1674 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1675 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1676 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1678 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1679 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1681 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1682 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1683 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1684 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1685 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1686 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1688 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1689 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1690 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1691 case Mode.U2_CH: /* nothing */ break;
1693 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1694 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1695 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1696 case Mode.I4_U4: /* nothing */ break;
1697 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1698 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1699 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1701 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1702 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1703 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1704 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1705 case Mode.U4_I4: /* nothing */ break;
1706 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1708 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1709 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1710 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1711 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1712 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1713 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1714 case Mode.I8_U8: /* nothing */ break;
1715 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1717 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1718 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1719 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1720 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1721 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1722 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1723 case Mode.U8_I8: /* nothing */ break;
1724 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1726 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1727 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1728 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1730 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1731 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1732 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1733 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1734 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1735 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1736 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1737 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1738 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1740 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1741 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1742 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1743 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1744 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1745 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1746 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1747 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1748 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1749 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1755 public class OpcodeCast : EmptyCast {
1759 public OpcodeCast (Expression child, Type return_type, OpCode op)
1760 : base (child, return_type)
1764 second_valid = false;
1767 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1768 : base (child, return_type)
1773 second_valid = true;
1776 public override Expression DoResolve (EmitContext ec)
1778 // This should never be invoked, we are born in fully
1779 // initialized state.
1784 public override void Emit (EmitContext ec)
1795 /// This kind of cast is used to encapsulate a child and cast it
1796 /// to the class requested
1798 public class ClassCast : EmptyCast {
1799 public ClassCast (Expression child, Type return_type)
1800 : base (child, return_type)
1805 public override Expression DoResolve (EmitContext ec)
1807 // This should never be invoked, we are born in fully
1808 // initialized state.
1813 public override void Emit (EmitContext ec)
1817 if (child.Type.IsGenericParameter)
1818 ec.ig.Emit (OpCodes.Box, child.Type);
1820 if (type.IsGenericParameter)
1821 ec.ig.Emit (OpCodes.Unbox_Any, type);
1823 ec.ig.Emit (OpCodes.Castclass, type);
1828 /// SimpleName expressions are formed of a single word and only happen at the beginning
1829 /// of a dotted-name.
1831 public class SimpleName : Expression {
1833 public readonly TypeArguments Arguments;
1836 public SimpleName (string name, Location l)
1842 public SimpleName (string name, TypeArguments args, Location l)
1849 public SimpleName (string name, TypeParameter[] type_params, Location l)
1854 Arguments = new TypeArguments (l);
1855 foreach (TypeParameter type_param in type_params)
1856 Arguments.Add (new TypeParameterExpr (type_param, l));
1859 public static string RemoveGenericArity (string name)
1862 StringBuilder sb = new StringBuilder ();
1863 while (start < name.Length) {
1864 int pos = name.IndexOf ('`', start);
1866 sb.Append (name.Substring (start));
1870 sb.Append (name.Substring (start, pos-start));
1873 while ((pos < name.Length) && Char.IsNumber (name [pos]))
1879 return sb.ToString ();
1882 public SimpleName GetMethodGroup ()
1884 return new SimpleName (RemoveGenericArity (Name), Arguments, loc);
1887 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1889 if (ec.IsFieldInitializer)
1890 Report.Error (236, l,
1891 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1894 if (name.LastIndexOf ('.') > 0)
1895 name = name.Substring (name.LastIndexOf ('.') + 1);
1898 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1903 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1905 return resolved_to != null && resolved_to.Type != null &&
1906 resolved_to.Type.Name == Name &&
1907 (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1910 public override Expression DoResolve (EmitContext ec)
1912 return SimpleNameResolve (ec, null, false);
1915 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1917 return SimpleNameResolve (ec, right_side, false);
1921 public Expression DoResolve (EmitContext ec, bool intermediate)
1923 return SimpleNameResolve (ec, null, intermediate);
1926 private bool IsNestedChild (Type t, Type parent)
1931 while (parent != null) {
1932 parent = TypeManager.DropGenericTypeArguments (parent);
1933 if (TypeManager.IsNestedChildOf (t, parent))
1936 parent = parent.BaseType;
1942 FullNamedExpression ResolveNested (IResolveContext ec, Type t)
1944 if (!t.IsGenericTypeDefinition)
1947 DeclSpace ds = ec.DeclContainer;
1948 while (ds != null) {
1949 if (IsNestedChild (t, ds.TypeBuilder))
1958 Type[] gen_params = t.GetGenericArguments ();
1960 int arg_count = Arguments != null ? Arguments.Count : 0;
1962 for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
1963 if (arg_count + ds.CountTypeParameters == gen_params.Length) {
1964 TypeArguments new_args = new TypeArguments (loc);
1965 foreach (TypeParameter param in ds.TypeParameters)
1966 new_args.Add (new TypeParameterExpr (param, loc));
1968 if (Arguments != null)
1969 new_args.Add (Arguments);
1971 return new ConstructedType (t, new_args, loc);
1978 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1980 FullNamedExpression fne = ec.DeclContainer.LookupGeneric (Name, loc);
1982 return fne.ResolveAsTypeStep (ec, silent);
1984 int errors = Report.Errors;
1985 fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1988 if (fne.Type == null)
1991 FullNamedExpression nested = ResolveNested (ec, fne.Type);
1993 return nested.ResolveAsTypeStep (ec, false);
1995 if (Arguments != null) {
1996 ConstructedType ct = new ConstructedType (fne, Arguments, loc);
1997 return ct.ResolveAsTypeStep (ec, false);
2003 if (silent || errors != Report.Errors)
2006 MemberCore mc = ec.DeclContainer.GetDefinition (Name);
2008 Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
2010 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
2016 // TODO: I am still not convinced about this. If someone else will need it
2017 // implement this as virtual property in MemberCore hierarchy
2018 string GetMemberType (MemberCore mc)
2020 if (mc is PropertyBase)
2024 if (mc is FieldBase)
2026 if (mc is MethodCore)
2028 if (mc is EnumMember)
2034 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2040 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2044 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2051 /// 7.5.2: Simple Names.
2053 /// Local Variables and Parameters are handled at
2054 /// parse time, so they never occur as SimpleNames.
2056 /// The `intermediate' flag is used by MemberAccess only
2057 /// and it is used to inform us that it is ok for us to
2058 /// avoid the static check, because MemberAccess might end
2059 /// up resolving the Name as a Type name and the access as
2060 /// a static type access.
2062 /// ie: Type Type; .... { Type.GetType (""); }
2064 /// Type is both an instance variable and a Type; Type.GetType
2065 /// is the static method not an instance method of type.
2067 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2069 Expression e = null;
2072 // Stage 1: Performed by the parser (binding to locals or parameters).
2074 Block current_block = ec.CurrentBlock;
2075 if (current_block != null){
2076 LocalInfo vi = current_block.GetLocalInfo (Name);
2078 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2079 if (right_side != null) {
2080 return var.ResolveLValue (ec, right_side, loc);
2082 ResolveFlags rf = ResolveFlags.VariableOrValue;
2084 rf |= ResolveFlags.DisableFlowAnalysis;
2085 return var.Resolve (ec, rf);
2089 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
2091 if (right_side != null)
2092 return pref.ResolveLValue (ec, right_side, loc);
2094 return pref.Resolve (ec);
2099 // Stage 2: Lookup members
2102 DeclSpace lookup_ds = ec.DeclContainer;
2103 Type almost_matched_type = null;
2104 ArrayList almost_matched = null;
2106 if (lookup_ds.TypeBuilder == null)
2109 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
2113 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2114 almost_matched_type = lookup_ds.TypeBuilder;
2115 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2118 lookup_ds =lookup_ds.Parent;
2119 } while (lookup_ds != null);
2121 if (e == null && ec.ContainerType != null)
2122 e = MemberLookup (ec, ec.ContainerType, Name, loc);
2125 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2126 almost_matched_type = ec.ContainerType;
2127 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2129 e = ResolveAsTypeStep (ec, true);
2133 if (almost_matched != null)
2134 almostMatchedMembers = almost_matched;
2135 if (almost_matched_type == null)
2136 almost_matched_type = ec.ContainerType;
2137 MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
2144 if (e is MemberExpr) {
2145 MemberExpr me = (MemberExpr) e;
2148 if (me.IsInstance) {
2149 if (ec.IsStatic || ec.IsFieldInitializer) {
2151 // Note that an MemberExpr can be both IsInstance and IsStatic.
2152 // An unresolved MethodGroupExpr can contain both kinds of methods
2153 // and each predicate is true if the MethodGroupExpr contains
2154 // at least one of that kind of method.
2158 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2159 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2160 return EmptyExpression.Null;
2164 // Pass the buck to MemberAccess and Invocation.
2166 left = EmptyExpression.Null;
2168 left = ec.GetThis (loc);
2171 left = new TypeExpression (ec.ContainerType, loc);
2174 e = me.ResolveMemberAccess (ec, left, loc, null);
2178 me = e as MemberExpr;
2182 if (Arguments != null) {
2183 MethodGroupExpr mg = me as MethodGroupExpr;
2187 return mg.ResolveGeneric (ec, Arguments);
2191 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2192 me.InstanceExpression.Type != me.DeclaringType &&
2193 !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2194 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2195 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2196 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2200 return (right_side != null)
2201 ? me.DoResolveLValue (ec, right_side)
2202 : me.DoResolve (ec);
2208 public override void Emit (EmitContext ec)
2211 // If this is ever reached, then we failed to
2212 // find the name as a namespace
2215 Error (103, "The name `" + Name +
2216 "' does not exist in the class `" +
2217 ec.DeclContainer.Name + "'");
2220 public override string ToString ()
2225 public override string GetSignatureForError ()
2232 /// Represents a namespace or a type. The name of the class was inspired by
2233 /// section 10.8.1 (Fully Qualified Names).
2235 public abstract class FullNamedExpression : Expression {
2236 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2241 public abstract string FullName {
2247 /// Expression that evaluates to a type
2249 public abstract class TypeExpr : FullNamedExpression {
2250 override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2252 TypeExpr t = DoResolveAsTypeStep (ec);
2256 eclass = ExprClass.Type;
2260 override public Expression DoResolve (EmitContext ec)
2262 return ResolveAsTypeTerminal (ec, false);
2265 override public void Emit (EmitContext ec)
2267 throw new Exception ("Should never be called");
2270 public virtual bool CheckAccessLevel (DeclSpace ds)
2272 return ds.CheckAccessLevel (Type);
2275 public virtual bool AsAccessible (DeclSpace ds, int flags)
2277 return ds.AsAccessible (Type, flags);
2280 public virtual bool IsClass {
2281 get { return Type.IsClass; }
2284 public virtual bool IsValueType {
2285 get { return Type.IsValueType; }
2288 public virtual bool IsInterface {
2289 get { return Type.IsInterface; }
2292 public virtual bool IsSealed {
2293 get { return Type.IsSealed; }
2296 public virtual bool CanInheritFrom ()
2298 if (Type == TypeManager.enum_type ||
2299 (Type == TypeManager.value_type && RootContext.StdLib) ||
2300 Type == TypeManager.multicast_delegate_type ||
2301 Type == TypeManager.delegate_type ||
2302 Type == TypeManager.array_type)
2308 protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
2310 public Type ResolveType (IResolveContext ec)
2312 TypeExpr t = ResolveAsTypeTerminal (ec, false);
2316 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (t.Type);
2317 if (obsolete_attr != null && !ec.IsInObsoleteScope) {
2318 AttributeTester.Report_ObsoleteMessage (obsolete_attr, Name, Location);
2324 public abstract string Name {
2328 public override bool Equals (object obj)
2330 TypeExpr tobj = obj as TypeExpr;
2334 return Type == tobj.Type;
2337 public override int GetHashCode ()
2339 return Type.GetHashCode ();
2342 public override string ToString ()
2349 /// Fully resolved Expression that already evaluated to a type
2351 public class TypeExpression : TypeExpr {
2352 public TypeExpression (Type t, Location l)
2355 eclass = ExprClass.Type;
2359 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2364 public override string Name {
2365 get { return Type.ToString (); }
2368 public override string FullName {
2369 get { return Type.FullName; }
2374 /// Used to create types from a fully qualified name. These are just used
2375 /// by the parser to setup the core types. A TypeLookupExpression is always
2376 /// classified as a type.
2378 public class TypeLookupExpression : TypeExpr {
2381 public TypeLookupExpression (string name)
2386 static readonly char [] dot_array = { '.' };
2387 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2392 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2394 string lookup_name = name;
2395 int pos = name.IndexOf ('.');
2397 rest = name.Substring (pos + 1);
2398 lookup_name = name.Substring (0, pos);
2401 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
2403 if (resolved != null && rest != null) {
2404 // Now handle the rest of the the name.
2405 string [] elements = rest.Split (dot_array);
2407 int count = elements.Length;
2409 while (i < count && resolved != null && resolved is Namespace) {
2410 Namespace ns = resolved as Namespace;
2411 element = elements [i++];
2412 lookup_name += "." + element;
2413 resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
2416 if (resolved != null && resolved is TypeExpr) {
2417 Type t = ((TypeExpr) resolved).Type;
2419 if (!ec.DeclContainer.CheckAccessLevel (t)) {
2421 lookup_name = t.FullName;
2428 t = TypeManager.GetNestedType (t, elements [i++]);
2433 if (resolved == null) {
2434 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2438 if (!(resolved is TypeExpr)) {
2439 resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
2443 type = ((TypeExpr) resolved).ResolveType (ec);
2447 public override string Name {
2448 get { return name; }
2451 public override string FullName {
2452 get { return name; }
2457 /// Represents an "unbound generic type", ie. typeof (Foo<>).
2460 public class UnboundTypeExpression : TypeExpr
2464 public UnboundTypeExpression (MemberName name, Location l)
2470 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2473 if (name.Left != null) {
2474 Expression lexpr = name.Left.GetTypeExpression ();
2475 expr = new MemberAccess (lexpr, name.Basename, loc);
2477 expr = new SimpleName (name.Basename, loc);
2480 FullNamedExpression fne = expr.ResolveAsTypeStep (ec, false);
2485 return new TypeExpression (type, loc);
2488 public override string Name {
2489 get { return name.FullName; }
2492 public override string FullName {
2493 get { return name.FullName; }
2497 public class TypeAliasExpression : TypeExpr {
2498 FullNamedExpression alias;
2503 public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
2509 eclass = ExprClass.Type;
2511 name = alias.FullName + "<" + args.ToString () + ">";
2513 name = alias.FullName;
2516 public override string Name {
2517 get { return alias.FullName; }
2520 public override string FullName {
2521 get { return name; }
2524 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2526 texpr = alias.ResolveAsTypeTerminal (ec, false);
2530 Type type = texpr.ResolveType (ec);
2531 int num_args = TypeManager.GetNumberOfTypeArguments (type);
2534 if (num_args == 0) {
2535 Report.Error (308, loc,
2536 "The non-generic type `{0}' cannot " +
2537 "be used with type arguments.",
2538 TypeManager.CSharpName (type));
2542 ConstructedType ctype = new ConstructedType (type, args, loc);
2543 return ctype.ResolveAsTypeTerminal (ec, false);
2544 } else if (num_args > 0) {
2545 Report.Error (305, loc,
2546 "Using the generic type `{0}' " +
2547 "requires {1} type arguments",
2548 TypeManager.CSharpName (type), num_args.ToString ());
2552 return new TypeExpression (type, loc);
2555 public override bool CheckAccessLevel (DeclSpace ds)
2557 return texpr.CheckAccessLevel (ds);
2560 public override bool AsAccessible (DeclSpace ds, int flags)
2562 return texpr.AsAccessible (ds, flags);
2565 public override bool IsClass {
2566 get { return texpr.IsClass; }
2569 public override bool IsValueType {
2570 get { return texpr.IsValueType; }
2573 public override bool IsInterface {
2574 get { return texpr.IsInterface; }
2577 public override bool IsSealed {
2578 get { return texpr.IsSealed; }
2583 /// This class denotes an expression which evaluates to a member
2584 /// of a struct or a class.
2586 public abstract class MemberExpr : Expression
2589 /// The name of this member.
2591 public abstract string Name {
2596 /// Whether this is an instance member.
2598 public abstract bool IsInstance {
2603 /// Whether this is a static member.
2605 public abstract bool IsStatic {
2610 /// The type which declares this member.
2612 public abstract Type DeclaringType {
2617 /// The instance expression associated with this member, if it's a
2618 /// non-static member.
2620 public Expression InstanceExpression;
2622 public static void error176 (Location loc, string name)
2624 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2625 "with an instance reference, qualify it with a type name instead", name);
2628 // TODO: possible optimalization
2629 // Cache resolved constant result in FieldBuilder <-> expression map
2630 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2631 SimpleName original)
2635 // original == null || original.Resolve (...) ==> left
2638 if (left is TypeExpr) {
2640 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2648 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2651 error176 (loc, GetSignatureForError ());
2655 InstanceExpression = left;
2660 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2665 if (InstanceExpression == EmptyExpression.Null) {
2666 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2670 if (InstanceExpression.Type.IsValueType) {
2671 if (InstanceExpression is IMemoryLocation) {
2672 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2674 LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
2675 InstanceExpression.Emit (ec);
2677 t.AddressOf (ec, AddressOp.Store);
2680 InstanceExpression.Emit (ec);
2682 if (prepare_for_load)
2683 ec.ig.Emit (OpCodes.Dup);
2688 /// MethodGroup Expression.
2690 /// This is a fully resolved expression that evaluates to a type
2692 public class MethodGroupExpr : MemberExpr {
2693 public MethodBase [] Methods;
2694 bool has_type_arguments = false;
2695 bool identical_type_name = false;
2698 public MethodGroupExpr (MemberInfo [] mi, Location l)
2700 Methods = new MethodBase [mi.Length];
2701 mi.CopyTo (Methods, 0);
2702 eclass = ExprClass.MethodGroup;
2703 type = TypeManager.object_type;
2707 public MethodGroupExpr (ArrayList list, Location l)
2709 Methods = new MethodBase [list.Count];
2712 list.CopyTo (Methods, 0);
2714 foreach (MemberInfo m in list){
2715 if (!(m is MethodBase)){
2716 Console.WriteLine ("Name " + m.Name);
2717 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2724 eclass = ExprClass.MethodGroup;
2725 type = TypeManager.object_type;
2728 public override Type DeclaringType {
2731 // We assume that the top-level type is in the end
2733 return Methods [Methods.Length - 1].DeclaringType;
2734 //return Methods [0].DeclaringType;
2738 public bool HasTypeArguments {
2740 return has_type_arguments;
2744 has_type_arguments = value;
2748 public bool IdenticalTypeName {
2750 return identical_type_name;
2754 identical_type_name = value;
2758 public bool IsBase {
2767 public override string GetSignatureForError ()
2769 return TypeManager.CSharpSignature (Methods [0]);
2772 public override string Name {
2774 return Methods [0].Name;
2778 public override bool IsInstance {
2780 foreach (MethodBase mb in Methods)
2788 public override bool IsStatic {
2790 foreach (MethodBase mb in Methods)
2798 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2799 SimpleName original)
2801 if (!(left is TypeExpr) &&
2802 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2803 IdenticalTypeName = true;
2805 return base.ResolveMemberAccess (ec, left, loc, original);
2808 override public Expression DoResolve (EmitContext ec)
2811 InstanceExpression = null;
2813 if (InstanceExpression != null) {
2814 InstanceExpression = InstanceExpression.DoResolve (ec);
2815 if (InstanceExpression == null)
2822 public void ReportUsageError ()
2824 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2825 Name + "()' is referenced without parentheses");
2828 override public void Emit (EmitContext ec)
2830 ReportUsageError ();
2833 bool RemoveMethods (bool keep_static)
2835 ArrayList smethods = new ArrayList ();
2837 foreach (MethodBase mb in Methods){
2838 if (mb.IsStatic == keep_static)
2842 if (smethods.Count == 0)
2845 Methods = new MethodBase [smethods.Count];
2846 smethods.CopyTo (Methods, 0);
2852 /// Removes any instance methods from the MethodGroup, returns
2853 /// false if the resulting set is empty.
2855 public bool RemoveInstanceMethods ()
2857 return RemoveMethods (true);
2861 /// Removes any static methods from the MethodGroup, returns
2862 /// false if the resulting set is empty.
2864 public bool RemoveStaticMethods ()
2866 return RemoveMethods (false);
2869 public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
2871 if (args.Resolve (ec) == false)
2874 Type[] atypes = args.Arguments;
2876 int first_count = 0;
2877 MethodInfo first = null;
2879 ArrayList list = new ArrayList ();
2880 foreach (MethodBase mb in Methods) {
2881 MethodInfo mi = mb as MethodInfo;
2882 if ((mi == null) || !mi.IsGenericMethod)
2885 Type[] gen_params = mi.GetGenericArguments ();
2887 if (first == null) {
2889 first_count = gen_params.Length;
2892 if (gen_params.Length != atypes.Length)
2895 list.Add (mi.MakeGenericMethod (atypes));
2898 if (list.Count > 0) {
2899 MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
2900 new_mg.InstanceExpression = InstanceExpression;
2901 new_mg.HasTypeArguments = true;
2902 new_mg.IsBase = IsBase;
2908 305, loc, "Using the generic method `{0}' " +
2909 "requires {1} type arguments", Name,
2910 first_count.ToString ());
2913 308, loc, "The non-generic method `{0}' " +
2914 "cannot be used with type arguments", Name);
2921 /// Fully resolved expression that evaluates to a Field
2923 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2924 public readonly FieldInfo FieldInfo;
2925 VariableInfo variable_info;
2927 LocalTemporary temp;
2929 bool in_initializer;
2931 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2934 this.in_initializer = in_initializer;
2937 public FieldExpr (FieldInfo fi, Location l)
2940 eclass = ExprClass.Variable;
2941 type = TypeManager.TypeToCoreType (fi.FieldType);
2945 public override string Name {
2947 return FieldInfo.Name;
2951 public override bool IsInstance {
2953 return !FieldInfo.IsStatic;
2957 public override bool IsStatic {
2959 return FieldInfo.IsStatic;
2963 public override Type DeclaringType {
2965 return FieldInfo.DeclaringType;
2969 public override string GetSignatureForError ()
2971 return TypeManager.GetFullNameSignature (FieldInfo);
2974 public VariableInfo VariableInfo {
2976 return variable_info;
2980 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2981 SimpleName original)
2983 FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
2985 Type t = fi.FieldType;
2987 if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
2988 IConstant ic = TypeManager.GetConstant (fi);
2991 ic = new ExternalConstant (fi);
2993 ic = ExternalConstant.CreateDecimal (fi);
2995 return base.ResolveMemberAccess (ec, left, loc, original);
2998 TypeManager.RegisterConstant (fi, ic);
3001 bool left_is_type = left is TypeExpr;
3002 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
3003 Report.SymbolRelatedToPreviousError (FieldInfo);
3004 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
3008 if (ic.ResolveValue ()) {
3009 if (!ec.IsInObsoleteScope)
3010 ic.CheckObsoleteness (loc);
3016 if (t.IsPointer && !ec.InUnsafe) {
3021 return base.ResolveMemberAccess (ec, left, loc, original);
3024 override public Expression DoResolve (EmitContext ec)
3026 return DoResolve (ec, false);
3029 Expression DoResolve (EmitContext ec, bool lvalue_instance)
3031 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
3032 if (FieldInfo.FieldType is TypeBuilder) {
3033 if (FieldInfo.IsStatic)
3034 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
3035 GetSignatureForError ());
3037 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
3038 TypeManager.CSharpName (DeclaringType), Name);
3040 if (FieldInfo.IsStatic)
3041 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
3044 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
3050 if (!FieldInfo.IsStatic){
3051 if (InstanceExpression == null){
3053 // This can happen when referencing an instance field using
3054 // a fully qualified type expression: TypeName.InstanceField = xxx
3056 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
3060 // Resolve the field's instance expression while flow analysis is turned
3061 // off: when accessing a field "a.b", we must check whether the field
3062 // "a.b" is initialized, not whether the whole struct "a" is initialized.
3064 if (lvalue_instance) {
3065 bool old_do_flow_analysis = ec.DoFlowAnalysis;
3066 ec.DoFlowAnalysis = false;
3067 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3068 ec.DoFlowAnalysis = old_do_flow_analysis;
3070 ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
3071 InstanceExpression = InstanceExpression.Resolve (ec, rf);
3074 if (InstanceExpression == null)
3078 if (!in_initializer && !ec.IsFieldInitializer) {
3079 ObsoleteAttribute oa;
3080 FieldBase f = TypeManager.GetField (FieldInfo);
3082 if (!ec.IsInObsoleteScope)
3083 f.CheckObsoleteness (loc);
3085 // To be sure that type is external because we do not register generated fields
3086 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
3087 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
3089 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
3093 AnonymousContainer am = ec.CurrentAnonymousMethod;
3095 if (!FieldInfo.IsStatic){
3096 if (!am.IsIterator && (ec.TypeContainer is Struct)){
3097 Report.Error (1673, loc,
3098 "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",
3102 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
3103 ec.CaptureField (this);
3107 // If the instance expression is a local variable or parameter.
3108 IVariable var = InstanceExpression as IVariable;
3109 if ((var == null) || (var.VariableInfo == null))
3112 VariableInfo vi = var.VariableInfo;
3113 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
3116 variable_info = vi.GetSubStruct (FieldInfo.Name);
3120 void Report_AssignToReadonly (Expression right_side)
3124 bool need_error_sig = false;
3125 if (right_side == EmptyExpression.LValueMemberAccess) {
3128 msg = "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)";
3131 msg = "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)";
3133 need_error_sig = true;
3134 } else if (IsStatic) {
3136 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
3139 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
3143 Report.Error (code, loc, msg, GetSignatureForError ());
3145 Report.Error (code, loc, msg);
3148 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3150 IVariable var = InstanceExpression as IVariable;
3151 if ((var != null) && (var.VariableInfo != null))
3152 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
3154 bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
3156 Expression e = DoResolve (ec, lvalue_instance);
3161 FieldBase fb = TypeManager.GetField (FieldInfo);
3165 if (!FieldInfo.IsInitOnly)
3169 // InitOnly fields can only be assigned in constructors
3172 if (ec.IsConstructor){
3173 if (IsStatic && !ec.IsStatic)
3174 Report_AssignToReadonly (right_side);
3177 if (ec.TypeContainer.CurrentType != null)
3178 ctype = ec.TypeContainer.CurrentType;
3180 ctype = ec.ContainerType;
3182 if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
3186 Report_AssignToReadonly (right_side);
3191 public override void CheckMarshallByRefAccess (Type container)
3193 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
3194 Report.SymbolRelatedToPreviousError (DeclaringType);
3195 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",
3196 GetSignatureForError ());
3200 public bool VerifyFixed ()
3202 IVariable variable = InstanceExpression as IVariable;
3203 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
3204 // We defer the InstanceExpression check after the variable check to avoid a
3205 // separate null check on InstanceExpression.
3206 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
3209 public override int GetHashCode()
3211 return FieldInfo.GetHashCode ();
3214 public override bool Equals (object obj)
3216 FieldExpr fe = obj as FieldExpr;
3220 if (FieldInfo != fe.FieldInfo)
3223 if (InstanceExpression == null || fe.InstanceExpression == null)
3226 return InstanceExpression.Equals (fe.InstanceExpression);
3229 public void Emit (EmitContext ec, bool leave_copy)
3231 ILGenerator ig = ec.ig;
3232 bool is_volatile = false;
3234 FieldBase f = TypeManager.GetField (FieldInfo);
3236 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3239 f.SetMemberIsUsed ();
3242 if (FieldInfo.IsStatic){
3244 ig.Emit (OpCodes.Volatile);
3246 ig.Emit (OpCodes.Ldsfld, FieldInfo);
3249 EmitInstance (ec, false);
3252 ig.Emit (OpCodes.Volatile);
3254 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
3257 ig.Emit (OpCodes.Ldflda, FieldInfo);
3258 ig.Emit (OpCodes.Ldflda, ff.Element);
3261 ig.Emit (OpCodes.Ldfld, FieldInfo);
3266 ec.ig.Emit (OpCodes.Dup);
3267 if (!FieldInfo.IsStatic) {
3268 temp = new LocalTemporary (ec, this.Type);
3274 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3276 FieldAttributes fa = FieldInfo.Attributes;
3277 bool is_static = (fa & FieldAttributes.Static) != 0;
3278 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3279 ILGenerator ig = ec.ig;
3280 prepared = prepare_for_load;
3282 if (is_readonly && !ec.IsConstructor){
3283 Report_AssignToReadonly (source);
3287 EmitInstance (ec, prepare_for_load);
3291 ec.ig.Emit (OpCodes.Dup);
3292 if (!FieldInfo.IsStatic) {
3293 temp = new LocalTemporary (ec, this.Type);
3298 if (FieldInfo is FieldBuilder){
3299 FieldBase f = TypeManager.GetField (FieldInfo);
3301 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3302 ig.Emit (OpCodes.Volatile);
3309 ig.Emit (OpCodes.Stsfld, FieldInfo);
3311 ig.Emit (OpCodes.Stfld, FieldInfo);
3317 public override void Emit (EmitContext ec)
3322 public void AddressOf (EmitContext ec, AddressOp mode)
3324 ILGenerator ig = ec.ig;
3326 if (FieldInfo is FieldBuilder){
3327 FieldBase f = TypeManager.GetField (FieldInfo);
3329 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3330 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3331 f.GetSignatureForError ());
3335 if ((mode & AddressOp.Store) != 0)
3337 if ((mode & AddressOp.Load) != 0)
3338 f.SetMemberIsUsed ();
3343 // Handle initonly fields specially: make a copy and then
3344 // get the address of the copy.
3347 if (FieldInfo.IsInitOnly){
3349 if (ec.IsConstructor){
3350 if (FieldInfo.IsStatic){
3362 local = ig.DeclareLocal (type);
3363 ig.Emit (OpCodes.Stloc, local);
3364 ig.Emit (OpCodes.Ldloca, local);
3369 if (FieldInfo.IsStatic){
3370 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3373 EmitInstance (ec, false);
3374 ig.Emit (OpCodes.Ldflda, FieldInfo);
3380 // A FieldExpr whose address can not be taken
3382 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3383 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3387 public new void AddressOf (EmitContext ec, AddressOp mode)
3389 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3394 /// Expression that evaluates to a Property. The Assign class
3395 /// might set the `Value' expression if we are in an assignment.
3397 /// This is not an LValue because we need to re-write the expression, we
3398 /// can not take data from the stack and store it.
3400 public class PropertyExpr : MemberExpr, IAssignMethod {
3401 public readonly PropertyInfo PropertyInfo;
3404 // This is set externally by the `BaseAccess' class
3407 MethodInfo getter, setter;
3412 LocalTemporary temp;
3415 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3417 public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
3420 eclass = ExprClass.PropertyAccess;
3424 type = TypeManager.TypeToCoreType (pi.PropertyType);
3426 ResolveAccessors (containerType);
3429 public override string Name {
3431 return PropertyInfo.Name;
3435 public override bool IsInstance {
3441 public override bool IsStatic {
3447 public override Type DeclaringType {
3449 return PropertyInfo.DeclaringType;
3453 public override string GetSignatureForError ()
3455 return TypeManager.GetFullNameSignature (PropertyInfo);
3458 void FindAccessors (Type invocation_type)
3460 const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3461 BindingFlags.Static | BindingFlags.Instance |
3462 BindingFlags.DeclaredOnly;
3464 Type current = PropertyInfo.DeclaringType;
3465 for (; current != null; current = current.BaseType) {
3466 MemberInfo[] group = TypeManager.MemberLookup (
3467 invocation_type, invocation_type, current,
3468 MemberTypes.Property, flags, PropertyInfo.Name, null);
3473 if (group.Length != 1)
3474 // Oooops, can this ever happen ?
3477 PropertyInfo pi = (PropertyInfo) group [0];
3480 getter = pi.GetGetMethod (true);
3483 setter = pi.GetSetMethod (true);
3485 MethodInfo accessor = getter != null ? getter : setter;
3487 if (!accessor.IsVirtual)
3493 // We also perform the permission checking here, as the PropertyInfo does not
3494 // hold the information for the accessibility of its setter/getter
3496 void ResolveAccessors (Type containerType)
3498 FindAccessors (containerType);
3500 if (getter != null) {
3501 MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
3502 IMethodData md = TypeManager.GetMethod (the_getter);
3504 md.SetMemberIsUsed ();
3506 AccessorTable [getter] = PropertyInfo;
3507 is_static = getter.IsStatic;
3510 if (setter != null) {
3511 MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter);
3512 IMethodData md = TypeManager.GetMethod (the_setter);
3514 md.SetMemberIsUsed ();
3516 AccessorTable [setter] = PropertyInfo;
3517 is_static = setter.IsStatic;
3521 bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
3524 InstanceExpression = null;
3528 if (InstanceExpression == null) {
3529 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3533 if (lvalue_instance)
3534 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3536 InstanceExpression = InstanceExpression.DoResolve (ec);
3537 if (InstanceExpression == null)
3540 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3542 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3543 InstanceExpression.Type != ec.ContainerType &&
3544 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3545 !InstanceExpression.Type.IsSubclassOf (ec.ContainerType)) {
3546 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3553 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3555 // TODO: correctly we should compare arguments but it will lead to bigger changes
3556 if (mi is MethodBuilder) {
3557 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3561 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3563 ParameterData iparams = TypeManager.GetParameterData (mi);
3564 sig.Append (getter ? "get_" : "set_");
3566 sig.Append (iparams.GetSignatureForError ());
3568 Report.SymbolRelatedToPreviousError (mi);
3569 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3570 Name, sig.ToString ());
3573 override public Expression DoResolve (EmitContext ec)
3578 if (getter != null){
3579 if (TypeManager.GetParameterData (getter).Count != 0){
3580 Error_PropertyNotFound (getter, true);
3585 if (getter == null){
3587 // The following condition happens if the PropertyExpr was
3588 // created, but is invalid (ie, the property is inaccessible),
3589 // and we did not want to embed the knowledge about this in
3590 // the caller routine. This only avoids double error reporting.
3595 if (InstanceExpression != EmptyExpression.Null) {
3596 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3597 TypeManager.GetFullNameSignature (PropertyInfo));
3602 bool must_do_cs1540_check = false;
3603 if (getter != null &&
3604 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3605 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3606 if (pm != null && pm.HasCustomAccessModifier) {
3607 Report.SymbolRelatedToPreviousError (pm);
3608 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3609 TypeManager.CSharpSignature (getter));
3612 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3616 if (!InstanceResolve (ec, false, must_do_cs1540_check))
3620 // Only base will allow this invocation to happen.
3622 if (IsBase && getter.IsAbstract) {
3623 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3627 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3637 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3639 if (right_side == EmptyExpression.OutAccess) {
3640 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
3641 GetSignatureForError ());
3645 if (right_side == EmptyExpression.LValueMemberAccess) {
3646 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
3647 GetSignatureForError ());
3651 if (setter == null){
3653 // The following condition happens if the PropertyExpr was
3654 // created, but is invalid (ie, the property is inaccessible),
3655 // and we did not want to embed the knowledge about this in
3656 // the caller routine. This only avoids double error reporting.
3660 Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
3661 GetSignatureForError ());
3665 if (TypeManager.GetParameterData (setter).Count != 1){
3666 Error_PropertyNotFound (setter, false);
3670 bool must_do_cs1540_check;
3671 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3672 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3673 if (pm != null && pm.HasCustomAccessModifier) {
3674 Report.SymbolRelatedToPreviousError (pm);
3675 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3676 TypeManager.CSharpSignature (setter));
3679 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3683 if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
3687 // Only base will allow this invocation to happen.
3689 if (IsBase && setter.IsAbstract){
3690 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3697 public override void Emit (EmitContext ec)
3702 public void Emit (EmitContext ec, bool leave_copy)
3705 // Special case: length of single dimension array property is turned into ldlen
3707 if ((getter == TypeManager.system_int_array_get_length) ||
3708 (getter == TypeManager.int_array_get_length)){
3709 Type iet = InstanceExpression.Type;
3712 // System.Array.Length can be called, but the Type does not
3713 // support invoking GetArrayRank, so test for that case first
3715 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3717 EmitInstance (ec, false);
3718 ec.ig.Emit (OpCodes.Ldlen);
3719 ec.ig.Emit (OpCodes.Conv_I4);
3724 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3727 ec.ig.Emit (OpCodes.Dup);
3729 temp = new LocalTemporary (ec, this.Type);
3736 // Implements the IAssignMethod interface for assignments
3738 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3740 Expression my_source = source;
3742 prepared = prepare_for_load;
3747 ec.ig.Emit (OpCodes.Dup);
3749 temp = new LocalTemporary (ec, this.Type);
3753 } else if (leave_copy) {
3756 temp = new LocalTemporary (ec, this.Type);
3762 ArrayList args = new ArrayList (1);
3763 args.Add (new Argument (my_source, Argument.AType.Expression));
3765 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3773 /// Fully resolved expression that evaluates to an Event
3775 public class EventExpr : MemberExpr {
3776 public readonly EventInfo EventInfo;
3779 MethodInfo add_accessor, remove_accessor;
3781 public EventExpr (EventInfo ei, Location loc)
3785 eclass = ExprClass.EventAccess;
3787 add_accessor = TypeManager.GetAddMethod (ei);
3788 remove_accessor = TypeManager.GetRemoveMethod (ei);
3790 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3793 if (EventInfo is MyEventBuilder){
3794 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3795 type = eb.EventType;
3798 type = EventInfo.EventHandlerType;
3801 public override string Name {
3803 return EventInfo.Name;
3807 public override bool IsInstance {
3813 public override bool IsStatic {
3819 public override Type DeclaringType {
3821 return EventInfo.DeclaringType;
3825 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3826 SimpleName original)
3829 // If the event is local to this class, we transform ourselves into a FieldExpr
3832 if (EventInfo.DeclaringType == ec.ContainerType ||
3833 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3834 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3837 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
3840 Report.Error (-200, loc, "Internal error!!");
3844 InstanceExpression = null;
3846 return ml.ResolveMemberAccess (ec, left, loc, original);
3850 return base.ResolveMemberAccess (ec, left, loc, original);
3854 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3857 InstanceExpression = null;
3861 if (InstanceExpression == null) {
3862 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3866 InstanceExpression = InstanceExpression.DoResolve (ec);
3867 if (InstanceExpression == null)
3871 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3872 // However, in the Event case, we reported a CS0122 instead.
3874 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3875 InstanceExpression.Type != ec.ContainerType &&
3876 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3877 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3884 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3886 return DoResolve (ec);
3889 public override Expression DoResolve (EmitContext ec)
3891 bool must_do_cs1540_check;
3892 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3893 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3894 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3898 if (!InstanceResolve (ec, must_do_cs1540_check))
3904 public override void Emit (EmitContext ec)
3906 if (InstanceExpression is This)
3907 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3909 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3910 "(except on the defining type)", Name);
3913 public override string GetSignatureForError ()
3915 return TypeManager.CSharpSignature (EventInfo);
3918 public void EmitAddOrRemove (EmitContext ec, Expression source)
3920 BinaryDelegate source_del = (BinaryDelegate) source;
3921 Expression handler = source_del.Right;
3923 Argument arg = new Argument (handler, Argument.AType.Expression);
3924 ArrayList args = new ArrayList ();
3928 if (source_del.IsAddition)
3929 Invocation.EmitCall (
3930 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3932 Invocation.EmitCall (
3933 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3938 public class TemporaryVariable : Expression, IMemoryLocation
3942 public TemporaryVariable (Type type, Location loc)
3946 eclass = ExprClass.Value;
3949 public override Expression DoResolve (EmitContext ec)
3954 TypeExpr te = new TypeExpression (type, loc);
3955 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3956 if (!li.Resolve (ec))
3959 AnonymousContainer am = ec.CurrentAnonymousMethod;
3960 if ((am != null) && am.IsIterator)
3961 ec.CaptureVariable (li);
3966 public override void Emit (EmitContext ec)
3968 ILGenerator ig = ec.ig;
3970 if (li.FieldBuilder != null) {
3971 ig.Emit (OpCodes.Ldarg_0);
3972 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3974 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3978 public void EmitLoadAddress (EmitContext ec)
3980 ILGenerator ig = ec.ig;
3982 if (li.FieldBuilder != null) {
3983 ig.Emit (OpCodes.Ldarg_0);
3984 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3986 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3990 public void Store (EmitContext ec, Expression right_side)
3992 if (li.FieldBuilder != null)
3993 ec.ig.Emit (OpCodes.Ldarg_0);
3995 right_side.Emit (ec);
3996 if (li.FieldBuilder != null) {
3997 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3999 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
4003 public void EmitThis (EmitContext ec)
4005 if (li.FieldBuilder != null) {
4006 ec.ig.Emit (OpCodes.Ldarg_0);
4010 public void EmitStore (ILGenerator ig)
4012 if (li.FieldBuilder != null)
4013 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
4015 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
4018 public void AddressOf (EmitContext ec, AddressOp mode)
4020 EmitLoadAddress (ec);