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 FullNamedExpression ResolveAsTypeStep (EmitContext ec)
221 return ResolveAsTypeStep (ec, false);
224 public virtual FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
230 // This is used to resolve the expression as a type, a null
231 // value will be returned if the expression is not a type
234 public TypeExpr ResolveAsTypeTerminal (EmitContext ec)
236 return ResolveAsTypeTerminal (ec, false);
239 public virtual TypeExpr ResolveAsTypeTerminal (EmitContext ec, bool silent)
241 int errors = Report.Errors;
243 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
248 if (fne.eclass != ExprClass.Type) {
249 if (!silent && (errors == Report.Errors))
250 fne.Error_UnexpectedKind (null, "type", loc);
254 TypeExpr te = fne as TypeExpr;
256 if (!te.CheckAccessLevel (ec.DeclSpace)) {
257 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
261 ConstructedType ct = te as ConstructedType;
262 if ((ct != null) && !ec.ResolvingTypeTree && !ec.ResolvingGenericMethod &&
263 !ct.CheckConstraints (ec))
270 public static void ErrorIsInaccesible (Location loc, string name)
272 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
275 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
277 Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
278 + " the qualifier must be of type `{2}' (or derived from it)",
279 TypeManager.GetFullNameSignature (m),
280 TypeManager.CSharpName (qualifier),
281 TypeManager.CSharpName (container));
285 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
287 if (Type.Name == target.Name){
288 Report.ExtraInformation (loc,
290 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
291 Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
296 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
297 GetSignatureForError (), TypeManager.CSharpName (target));
301 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
302 bool b = Convert.ExplicitNumericConversion (e, target) != null;
304 if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
305 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
306 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
310 if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
311 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
312 GetSignatureForError (), TypeManager.CSharpName (target));
316 Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
317 Type == TypeManager.anonymous_method_type ?
318 "anonymous method" : "`" + GetSignatureForError () + "'",
319 TypeManager.CSharpName (target));
322 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
324 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
325 TypeManager.CSharpName (type), name);
328 ResolveFlags ExprClassToResolveFlags ()
332 case ExprClass.Namespace:
333 return ResolveFlags.Type;
335 case ExprClass.MethodGroup:
336 return ResolveFlags.MethodGroup;
338 case ExprClass.Value:
339 case ExprClass.Variable:
340 case ExprClass.PropertyAccess:
341 case ExprClass.EventAccess:
342 case ExprClass.IndexerAccess:
343 return ResolveFlags.VariableOrValue;
346 throw new Exception ("Expression " + GetType () +
347 " ExprClass is Invalid after resolve");
353 /// Resolves an expression and performs semantic analysis on it.
357 /// Currently Resolve wraps DoResolve to perform sanity
358 /// checking and assertion checking on what we expect from Resolve.
360 public Expression Resolve (EmitContext ec, ResolveFlags flags)
362 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
363 return ResolveAsTypeStep (ec, false);
365 bool old_do_flow_analysis = ec.DoFlowAnalysis;
366 bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;
367 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
368 ec.DoFlowAnalysis = false;
369 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
370 ec.OmitStructFlowAnalysis = true;
373 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
374 if (this is SimpleName)
375 e = ((SimpleName) this).DoResolve (ec, intermediate);
380 ec.DoFlowAnalysis = old_do_flow_analysis;
381 ec.OmitStructFlowAnalysis = old_omit_struct_analysis;
386 if ((flags & e.ExprClassToResolveFlags ()) == 0) {
387 e.Error_UnexpectedKind (flags, loc);
391 if (e.type == null && !(e is Namespace)) {
392 throw new Exception (
393 "Expression " + e.GetType () +
394 " did not set its type after Resolve\n" +
395 "called from: " + this.GetType ());
402 /// Resolves an expression and performs semantic analysis on it.
404 public Expression Resolve (EmitContext ec)
406 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
408 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
409 ((MethodGroupExpr) e).ReportUsageError ();
415 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
417 Expression e = Resolve (ec);
421 Constant c = e as Constant;
425 EmptyCast empty = e as EmptyCast;
427 c = empty.Child as Constant;
429 // TODO: not sure about this maybe there is easier way how to use EmptyCast
436 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
441 /// Resolves an expression for LValue assignment
445 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
446 /// checking and assertion checking on what we expect from Resolve
448 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
450 int errors = Report.Errors;
451 Expression e = DoResolveLValue (ec, right_side);
454 if (errors == Report.Errors)
455 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
460 if (e.eclass == ExprClass.Invalid)
461 throw new Exception ("Expression " + e +
462 " ExprClass is Invalid after resolve");
464 if (e.eclass == ExprClass.MethodGroup) {
465 ((MethodGroupExpr) e).ReportUsageError ();
469 if ((e.type == null) && !(e is ConstructedType))
470 throw new Exception ("Expression " + e +
471 " did not set its type after Resolve");
478 /// Emits the code for the expression
482 /// The Emit method is invoked to generate the code
483 /// for the expression.
485 public abstract void Emit (EmitContext ec);
487 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
490 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
494 /// Protected constructor. Only derivate types should
495 /// be able to be created
498 protected Expression ()
500 eclass = ExprClass.Invalid;
505 /// Returns a literalized version of a literal FieldInfo
509 /// The possible return values are:
510 /// IntConstant, UIntConstant
511 /// LongLiteral, ULongConstant
512 /// FloatConstant, DoubleConstant
515 /// The value returned is already resolved.
517 public static Constant Constantify (object v, Type t)
519 if (t == TypeManager.int32_type)
520 return new IntConstant ((int) v, Location.Null);
521 else if (t == TypeManager.uint32_type)
522 return new UIntConstant ((uint) v, Location.Null);
523 else if (t == TypeManager.int64_type)
524 return new LongConstant ((long) v, Location.Null);
525 else if (t == TypeManager.uint64_type)
526 return new ULongConstant ((ulong) v, Location.Null);
527 else if (t == TypeManager.float_type)
528 return new FloatConstant ((float) v, Location.Null);
529 else if (t == TypeManager.double_type)
530 return new DoubleConstant ((double) v, Location.Null);
531 else if (t == TypeManager.string_type)
532 return new StringConstant ((string) v, Location.Null);
533 else if (t == TypeManager.short_type)
534 return new ShortConstant ((short)v, Location.Null);
535 else if (t == TypeManager.ushort_type)
536 return new UShortConstant ((ushort)v, Location.Null);
537 else if (t == TypeManager.sbyte_type)
538 return new SByteConstant ((sbyte)v, Location.Null);
539 else if (t == TypeManager.byte_type)
540 return new ByteConstant ((byte)v, Location.Null);
541 else if (t == TypeManager.char_type)
542 return new CharConstant ((char)v, Location.Null);
543 else if (t == TypeManager.bool_type)
544 return new BoolConstant ((bool) v, Location.Null);
545 else if (t == TypeManager.decimal_type)
546 return new DecimalConstant ((decimal) v, Location.Null);
547 else if (TypeManager.IsEnumType (t)){
548 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
550 real_type = System.Enum.GetUnderlyingType (real_type);
552 Constant e = Constantify (v, real_type);
554 return new EnumConstant (e, t);
555 } else if (v == null && !TypeManager.IsValueType (t))
556 return new NullLiteral (Location.Null);
558 throw new Exception ("Unknown type for constant (" + t +
563 /// Returns a fully formed expression after a MemberLookup
566 public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
569 return new EventExpr ((EventInfo) mi, loc);
570 else if (mi is FieldInfo)
571 return new FieldExpr ((FieldInfo) mi, loc);
572 else if (mi is PropertyInfo)
573 return new PropertyExpr (ec, (PropertyInfo) mi, loc);
574 else if (mi is Type){
575 return new TypeExpression ((System.Type) mi, loc);
581 protected static ArrayList almostMatchedMembers = new ArrayList (4);
584 // FIXME: Probably implement a cache for (t,name,current_access_set)?
586 // This code could use some optimizations, but we need to do some
587 // measurements. For example, we could use a delegate to `flag' when
588 // something can not any longer be a method-group (because it is something
592 // If the return value is an Array, then it is an array of
595 // If the return value is an MemberInfo, it is anything, but a Method
599 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
600 // the arguments here and have MemberLookup return only the methods that
601 // match the argument count/type, unlike we are doing now (we delay this
604 // This is so we can catch correctly attempts to invoke instance methods
605 // from a static body (scan for error 120 in ResolveSimpleName).
608 // FIXME: Potential optimization, have a static ArrayList
611 public static Expression MemberLookup (EmitContext ec, Type queried_type, string name,
612 MemberTypes mt, BindingFlags bf, Location loc)
614 return MemberLookup (ec, ec.ContainerType, null, queried_type, name, mt, bf, loc);
618 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
619 // `qualifier_type' or null to lookup members in the current class.
622 public static Expression MemberLookup (EmitContext ec, Type container_type,
623 Type qualifier_type, Type queried_type,
624 string name, MemberTypes mt,
625 BindingFlags bf, Location loc)
627 almostMatchedMembers.Clear ();
629 MemberInfo [] mi = TypeManager.MemberLookup (
630 container_type, qualifier_type, queried_type, mt, bf, name,
631 almostMatchedMembers);
636 int count = mi.Length;
638 if (mi [0] is MethodBase)
639 return new MethodGroupExpr (mi, loc);
644 return ExprClassFromMemberInfo (ec, mi [0], loc);
647 public const MemberTypes AllMemberTypes =
648 MemberTypes.Constructor |
652 MemberTypes.NestedType |
653 MemberTypes.Property;
655 public const BindingFlags AllBindingFlags =
656 BindingFlags.Public |
657 BindingFlags.Static |
658 BindingFlags.Instance;
660 public static Expression MemberLookup (EmitContext ec, Type queried_type,
661 string name, Location loc)
663 return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
664 AllMemberTypes, AllBindingFlags, loc);
667 public static Expression MemberLookup (EmitContext ec, Type qualifier_type,
668 Type queried_type, string name, Location loc)
670 if (ec.ResolvingTypeTree)
671 return MemberLookup (ec, ec.ContainerType, qualifier_type,
672 queried_type, name, MemberTypes.NestedType,
673 AllBindingFlags, loc);
675 return MemberLookup (ec, ec.ContainerType, qualifier_type,
676 queried_type, name, AllMemberTypes,
677 AllBindingFlags, loc);
680 public static Expression MethodLookup (EmitContext ec, Type queried_type,
681 string name, Location loc)
683 return MemberLookup (ec, ec.ContainerType, null, queried_type, name,
684 MemberTypes.Method, AllBindingFlags, loc);
688 /// This is a wrapper for MemberLookup that is not used to "probe", but
689 /// to find a final definition. If the final definition is not found, we
690 /// look for private members and display a useful debugging message if we
693 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
694 Type queried_type, string name,
697 return MemberLookupFinal (ec, qualifier_type, queried_type, name,
698 AllMemberTypes, AllBindingFlags, loc);
701 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
702 Type queried_type, string name,
703 MemberTypes mt, BindingFlags bf,
708 int errors = Report.Errors;
710 e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
713 if (e == null && errors == Report.Errors)
714 // No errors were reported by MemberLookup, but there was an error.
715 MemberLookupFailed (ec, qualifier_type, queried_type, name, null, true, loc);
720 public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
721 Type queried_type, string name,
722 string class_name, bool complain_if_none_found,
725 if (almostMatchedMembers.Count != 0) {
726 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
727 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
728 for (int j = 0; j < i; ++j) {
729 if (m == almostMatchedMembers [j]) {
737 Type declaring_type = m.DeclaringType;
739 Report.SymbolRelatedToPreviousError (m);
740 if (qualifier_type == null) {
741 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
742 TypeManager.CSharpName (m.DeclaringType),
743 TypeManager.CSharpName (ec.ContainerType));
744 } else if (qualifier_type != ec.ContainerType &&
745 TypeManager.IsNestedFamilyAccessible (ec.ContainerType, declaring_type)) {
746 // Although a derived class can access protected members of
747 // its base class it cannot do so through an instance of the
748 // base class (CS1540). If the qualifier_type is a base of the
749 // ec.ContainerType and the lookup succeeds with the latter one,
750 // then we are in this situation.
751 Error_CannotAccessProtected (loc, m, qualifier_type, ec.ContainerType);
753 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
756 almostMatchedMembers.Clear ();
760 MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
761 AllMemberTypes, AllBindingFlags |
762 BindingFlags.NonPublic, name, null);
764 if (lookup == null) {
765 if (!complain_if_none_found)
768 if (class_name != null)
769 Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
772 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
776 if (TypeManager.MemberLookup (queried_type, null, queried_type,
777 AllMemberTypes, AllBindingFlags |
778 BindingFlags.NonPublic, name, null) == null) {
779 if ((lookup.Length == 1) && (lookup [0] is Type)) {
780 Type t = (Type) lookup [0];
782 Report.Error (305, loc,
783 "Using the generic type `{0}' " +
784 "requires {1} type arguments",
785 TypeManager.CSharpName (t),
786 TypeManager.GetNumberOfTypeArguments (t).ToString ());
791 MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
792 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
793 if (name == ".ctor" && ml.Count == 0)
795 Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
799 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
803 /// Returns an expression that can be used to invoke operator true
804 /// on the expression if it exists.
806 static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
808 return GetOperatorTrueOrFalse (ec, e, true, loc);
812 /// Returns an expression that can be used to invoke operator false
813 /// on the expression if it exists.
815 static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
817 return GetOperatorTrueOrFalse (ec, e, false, loc);
820 static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
823 Expression operator_group;
825 if (TypeManager.IsNullableType (e.Type))
826 return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
828 operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
829 if (operator_group == null)
832 ArrayList arguments = new ArrayList ();
833 arguments.Add (new Argument (e, Argument.AType.Expression));
834 method = Invocation.OverloadResolve (
835 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
840 return new StaticCallExpr ((MethodInfo) method, arguments, loc);
844 /// Resolves the expression `e' into a boolean expression: either through
845 /// an implicit conversion, or through an `operator true' invocation
847 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
853 if (e.Type == TypeManager.bool_type)
856 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
858 if (converted != null)
862 // If no implicit conversion to bool exists, try using `operator true'
864 converted = Expression.GetOperatorTrue (ec, e, loc);
865 if (converted == null){
866 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
872 public virtual string ExprClassName
876 case ExprClass.Invalid:
878 case ExprClass.Value:
880 case ExprClass.Variable:
882 case ExprClass.Namespace:
886 case ExprClass.MethodGroup:
887 return "method group";
888 case ExprClass.PropertyAccess:
889 return "property access";
890 case ExprClass.EventAccess:
891 return "event access";
892 case ExprClass.IndexerAccess:
893 return "indexer access";
894 case ExprClass.Nothing:
897 throw new Exception ("Should not happen");
902 /// Reports that we were expecting `expr' to be of class `expected'
904 public void Error_UnexpectedKind (EmitContext ec, string expected, Location loc)
906 Error_UnexpectedKind (ec, expected, ExprClassName, loc);
909 public void Error_UnexpectedKind (EmitContext ec, string expected, string was, Location loc)
911 string name = GetSignatureForError ();
913 name = ec.DeclSpace.GetSignatureForError () + '.' + name;
915 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
916 name, was, expected);
919 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
921 string [] valid = new string [4];
924 if ((flags & ResolveFlags.VariableOrValue) != 0) {
925 valid [count++] = "variable";
926 valid [count++] = "value";
929 if ((flags & ResolveFlags.Type) != 0)
930 valid [count++] = "type";
932 if ((flags & ResolveFlags.MethodGroup) != 0)
933 valid [count++] = "method group";
936 valid [count++] = "unknown";
938 StringBuilder sb = new StringBuilder (valid [0]);
939 for (int i = 1; i < count - 1; i++) {
941 sb.Append (valid [i]);
944 sb.Append ("' or `");
945 sb.Append (valid [count - 1]);
948 Report.Error (119, loc,
949 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
952 public static void UnsafeError (Location loc)
954 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
958 // Load the object from the pointer.
960 public static void LoadFromPtr (ILGenerator ig, Type t)
962 if (t == TypeManager.int32_type)
963 ig.Emit (OpCodes.Ldind_I4);
964 else if (t == TypeManager.uint32_type)
965 ig.Emit (OpCodes.Ldind_U4);
966 else if (t == TypeManager.short_type)
967 ig.Emit (OpCodes.Ldind_I2);
968 else if (t == TypeManager.ushort_type)
969 ig.Emit (OpCodes.Ldind_U2);
970 else if (t == TypeManager.char_type)
971 ig.Emit (OpCodes.Ldind_U2);
972 else if (t == TypeManager.byte_type)
973 ig.Emit (OpCodes.Ldind_U1);
974 else if (t == TypeManager.sbyte_type)
975 ig.Emit (OpCodes.Ldind_I1);
976 else if (t == TypeManager.uint64_type)
977 ig.Emit (OpCodes.Ldind_I8);
978 else if (t == TypeManager.int64_type)
979 ig.Emit (OpCodes.Ldind_I8);
980 else if (t == TypeManager.float_type)
981 ig.Emit (OpCodes.Ldind_R4);
982 else if (t == TypeManager.double_type)
983 ig.Emit (OpCodes.Ldind_R8);
984 else if (t == TypeManager.bool_type)
985 ig.Emit (OpCodes.Ldind_I1);
986 else if (t == TypeManager.intptr_type)
987 ig.Emit (OpCodes.Ldind_I);
988 else if (TypeManager.IsEnumType (t)) {
989 if (t == TypeManager.enum_type)
990 ig.Emit (OpCodes.Ldind_Ref);
992 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
993 } else if (t.IsValueType || t.IsGenericParameter)
994 ig.Emit (OpCodes.Ldobj, t);
995 else if (t.IsPointer)
996 ig.Emit (OpCodes.Ldind_I);
998 ig.Emit (OpCodes.Ldind_Ref);
1002 // The stack contains the pointer and the value of type `type'
1004 public static void StoreFromPtr (ILGenerator ig, Type type)
1006 if (TypeManager.IsEnumType (type))
1007 type = TypeManager.EnumToUnderlying (type);
1008 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
1009 ig.Emit (OpCodes.Stind_I4);
1010 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
1011 ig.Emit (OpCodes.Stind_I8);
1012 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
1013 type == TypeManager.ushort_type)
1014 ig.Emit (OpCodes.Stind_I2);
1015 else if (type == TypeManager.float_type)
1016 ig.Emit (OpCodes.Stind_R4);
1017 else if (type == TypeManager.double_type)
1018 ig.Emit (OpCodes.Stind_R8);
1019 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1020 type == TypeManager.bool_type)
1021 ig.Emit (OpCodes.Stind_I1);
1022 else if (type == TypeManager.intptr_type)
1023 ig.Emit (OpCodes.Stind_I);
1024 else if (type.IsValueType || type.IsGenericParameter)
1025 ig.Emit (OpCodes.Stobj, type);
1027 ig.Emit (OpCodes.Stind_Ref);
1031 // Returns the size of type `t' if known, otherwise, 0
1033 public static int GetTypeSize (Type t)
1035 t = TypeManager.TypeToCoreType (t);
1036 if (t == TypeManager.int32_type ||
1037 t == TypeManager.uint32_type ||
1038 t == TypeManager.float_type)
1040 else if (t == TypeManager.int64_type ||
1041 t == TypeManager.uint64_type ||
1042 t == TypeManager.double_type)
1044 else if (t == TypeManager.byte_type ||
1045 t == TypeManager.sbyte_type ||
1046 t == TypeManager.bool_type)
1048 else if (t == TypeManager.short_type ||
1049 t == TypeManager.char_type ||
1050 t == TypeManager.ushort_type)
1052 else if (t == TypeManager.decimal_type)
1058 public static void Error_NegativeArrayIndex (Location loc)
1060 Report.Error (248, loc, "Cannot create an array with a negative size");
1063 protected void Error_CannotCallAbstractBase (string name)
1065 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1069 // Converts `source' to an int, uint, long or ulong.
1071 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1075 bool old_checked = ec.CheckState;
1076 ec.CheckState = true;
1078 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1079 if (target == null){
1080 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1081 if (target == null){
1082 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1083 if (target == null){
1084 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1086 source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1090 ec.CheckState = old_checked;
1093 // Only positive constants are allowed at compile time
1095 if (target is Constant){
1096 if (target is IntConstant){
1097 if (((IntConstant) target).Value < 0){
1098 Error_NegativeArrayIndex (loc);
1103 if (target is LongConstant){
1104 if (((LongConstant) target).Value < 0){
1105 Error_NegativeArrayIndex (loc);
1118 /// This is just a base class for expressions that can
1119 /// appear on statements (invocations, object creation,
1120 /// assignments, post/pre increment and decrement). The idea
1121 /// being that they would support an extra Emition interface that
1122 /// does not leave a result on the stack.
1124 public abstract class ExpressionStatement : Expression {
1126 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1128 Expression e = Resolve (ec);
1132 ExpressionStatement es = e as ExpressionStatement;
1134 Error (201, "Only assignment, call, increment, decrement and new object " +
1135 "expressions can be used as a statement");
1141 /// Requests the expression to be emitted in a `statement'
1142 /// context. This means that no new value is left on the
1143 /// stack after invoking this method (constrasted with
1144 /// Emit that will always leave a value on the stack).
1146 public abstract void EmitStatement (EmitContext ec);
1150 /// This kind of cast is used to encapsulate the child
1151 /// whose type is child.Type into an expression that is
1152 /// reported to return "return_type". This is used to encapsulate
1153 /// expressions which have compatible types, but need to be dealt
1154 /// at higher levels with.
1156 /// For example, a "byte" expression could be encapsulated in one
1157 /// of these as an "unsigned int". The type for the expression
1158 /// would be "unsigned int".
1161 public class EmptyCast : Expression {
1162 protected Expression child;
1164 public Expression Child {
1170 public EmptyCast (Expression child, Type return_type)
1172 eclass = child.eclass;
1173 loc = child.Location;
1178 public override Expression DoResolve (EmitContext ec)
1180 // This should never be invoked, we are born in fully
1181 // initialized state.
1186 public override void Emit (EmitContext ec)
1192 /// This is a numeric cast to a Decimal
1194 public class CastToDecimal : EmptyCast {
1196 MethodInfo conversion_operator;
1198 public CastToDecimal (Expression child)
1199 : this (child, false)
1203 public CastToDecimal (Expression child, bool find_explicit)
1204 : base (child, TypeManager.decimal_type)
1206 conversion_operator = GetConversionOperator (find_explicit);
1208 if (conversion_operator == null)
1209 throw new InternalErrorException ("Outer conversion routine is out of sync");
1212 // Returns the implicit operator that converts from
1213 // 'child.Type' to System.Decimal.
1214 MethodInfo GetConversionOperator (bool find_explicit)
1216 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1218 MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1219 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1221 foreach (MethodInfo oper in mi) {
1222 ParameterData pd = TypeManager.GetParameterData (oper);
1224 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1230 public override void Emit (EmitContext ec)
1232 ILGenerator ig = ec.ig;
1235 ig.Emit (OpCodes.Call, conversion_operator);
1240 /// This is an explicit numeric cast from a Decimal
1242 public class CastFromDecimal : EmptyCast
1244 static IDictionary operators;
1246 public CastFromDecimal (Expression child, Type return_type)
1247 : base (child, return_type)
1249 if (child.Type != TypeManager.decimal_type)
1250 throw new InternalErrorException (
1251 "The expected type is Decimal, instead it is " + child.Type.FullName);
1254 // Returns the explicit operator that converts from an
1255 // express of type System.Decimal to 'type'.
1256 public Expression Resolve ()
1258 if (operators == null) {
1259 MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1260 TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1261 BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1263 operators = new System.Collections.Specialized.HybridDictionary ();
1264 foreach (MethodInfo oper in all_oper) {
1265 ParameterData pd = TypeManager.GetParameterData (oper);
1266 if (pd.ParameterType (0) == TypeManager.decimal_type)
1267 operators.Add (oper.ReturnType, oper);
1271 return operators.Contains (type) ? this : null;
1274 public override void Emit (EmitContext ec)
1276 ILGenerator ig = ec.ig;
1279 ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1284 // We need to special case this since an empty cast of
1285 // a NullLiteral is still a Constant
1287 public class NullCast : Constant {
1288 public Constant child;
1290 public NullCast (Constant child, Type return_type):
1291 base (Location.Null)
1293 eclass = child.eclass;
1298 override public string AsString ()
1303 public override object GetValue ()
1308 public override Expression DoResolve (EmitContext ec)
1310 // This should never be invoked, we are born in fully
1311 // initialized state.
1316 public override void Emit (EmitContext ec)
1321 public override Constant Increment ()
1323 throw new NotSupportedException ();
1326 public override bool IsDefaultValue {
1332 public override bool IsNegative {
1338 public override Constant Reduce (EmitContext ec, Type target_type)
1340 if (type == target_type)
1341 return child.Reduce (ec, target_type);
1350 /// This class is used to wrap literals which belong inside Enums
1352 public class EnumConstant : Constant {
1353 public Constant Child;
1355 public EnumConstant (Constant child, Type enum_type):
1356 base (child.Location)
1358 eclass = child.eclass;
1363 public override Expression DoResolve (EmitContext ec)
1365 // This should never be invoked, we are born in fully
1366 // initialized state.
1371 public override void Emit (EmitContext ec)
1376 public override string GetSignatureForError()
1378 return TypeManager.CSharpName (Type);
1381 public override object GetValue ()
1383 return Child.GetValue ();
1386 public override object GetTypedValue ()
1388 // FIXME: runtime is not ready to work with just emited enums
1389 if (!RootContext.StdLib) {
1390 return Child.GetValue ();
1393 return System.Enum.ToObject (type, Child.GetValue ());
1396 public override string AsString ()
1398 return Child.AsString ();
1401 public override DoubleConstant ConvertToDouble ()
1403 return Child.ConvertToDouble ();
1406 public override FloatConstant ConvertToFloat ()
1408 return Child.ConvertToFloat ();
1411 public override ULongConstant ConvertToULong ()
1413 return Child.ConvertToULong ();
1416 public override LongConstant ConvertToLong ()
1418 return Child.ConvertToLong ();
1421 public override UIntConstant ConvertToUInt ()
1423 return Child.ConvertToUInt ();
1426 public override IntConstant ConvertToInt ()
1428 return Child.ConvertToInt ();
1431 public override Constant Increment()
1433 return new EnumConstant (Child.Increment (), type);
1436 public override bool IsDefaultValue {
1438 return Child.IsDefaultValue;
1442 public override bool IsZeroInteger {
1443 get { return Child.IsZeroInteger; }
1446 public override bool IsNegative {
1448 return Child.IsNegative;
1452 public override Constant Reduce(EmitContext ec, Type target_type)
1454 if (Child.Type == target_type)
1457 return Child.Reduce (ec, target_type);
1460 public override Constant ToType (Type type, Location loc)
1463 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1464 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1467 if (type.UnderlyingSystemType != Child.Type)
1468 Child = Child.ToType (type.UnderlyingSystemType, loc);
1472 if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){
1473 Error_ValueCannotBeConverted (loc, type, false);
1477 return Child.ToType (type, loc);
1483 /// This kind of cast is used to encapsulate Value Types in objects.
1485 /// The effect of it is to box the value type emitted by the previous
1488 public class BoxedCast : EmptyCast {
1490 public BoxedCast (Expression expr, Type target_type)
1491 : base (expr, target_type)
1493 eclass = ExprClass.Value;
1496 public override Expression DoResolve (EmitContext ec)
1498 // This should never be invoked, we are born in fully
1499 // initialized state.
1504 public override void Emit (EmitContext ec)
1508 ec.ig.Emit (OpCodes.Box, child.Type);
1512 public class UnboxCast : EmptyCast {
1513 public UnboxCast (Expression expr, Type return_type)
1514 : base (expr, return_type)
1518 public override Expression DoResolve (EmitContext ec)
1520 // This should never be invoked, we are born in fully
1521 // initialized state.
1526 public override void Emit (EmitContext ec)
1529 ILGenerator ig = ec.ig;
1532 if (t.IsGenericParameter)
1533 ig.Emit (OpCodes.Unbox_Any, t);
1535 ig.Emit (OpCodes.Unbox, t);
1537 LoadFromPtr (ig, t);
1543 /// This is used to perform explicit numeric conversions.
1545 /// Explicit numeric conversions might trigger exceptions in a checked
1546 /// context, so they should generate the conv.ovf opcodes instead of
1549 public class ConvCast : EmptyCast {
1550 public enum Mode : byte {
1551 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1553 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1554 U2_I1, U2_U1, U2_I2, U2_CH,
1555 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1556 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1557 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1558 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1559 CH_I1, CH_U1, CH_I2,
1560 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1561 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1566 public ConvCast (Expression child, Type return_type, Mode m)
1567 : base (child, return_type)
1572 public override Expression DoResolve (EmitContext ec)
1574 // This should never be invoked, we are born in fully
1575 // initialized state.
1580 public override string ToString ()
1582 return String.Format ("ConvCast ({0}, {1})", mode, child);
1585 public override void Emit (EmitContext ec)
1587 ILGenerator ig = ec.ig;
1593 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1594 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1595 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1596 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1597 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1599 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1600 case Mode.U1_CH: /* nothing */ break;
1602 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1603 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1604 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1605 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1606 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1607 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1609 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1610 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1611 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1612 case Mode.U2_CH: /* nothing */ break;
1614 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1615 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1616 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1617 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1618 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1619 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1620 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1622 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1623 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1624 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1625 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1626 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1627 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1629 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1630 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1631 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1632 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1633 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1634 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1635 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1636 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1638 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1639 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1640 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1641 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1642 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1643 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1644 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1645 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1647 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1648 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1649 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1651 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1652 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1653 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1654 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1655 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1656 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1657 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1658 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1659 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1661 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1662 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1663 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1664 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1665 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1666 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1667 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1668 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1669 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1670 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1674 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1675 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1676 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1677 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1678 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1680 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1681 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1683 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1684 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1685 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1686 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1687 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1688 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1690 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1691 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1692 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1693 case Mode.U2_CH: /* nothing */ break;
1695 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1696 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1697 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1698 case Mode.I4_U4: /* nothing */ break;
1699 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1700 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1701 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1703 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1704 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1705 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1706 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1707 case Mode.U4_I4: /* nothing */ break;
1708 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1710 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1711 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1712 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1713 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1714 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1715 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1716 case Mode.I8_U8: /* nothing */ break;
1717 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1719 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1720 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1721 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1722 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1723 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1724 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1725 case Mode.U8_I8: /* nothing */ break;
1726 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1728 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1729 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1730 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1732 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1733 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1734 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1735 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1736 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1737 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1738 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1739 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1740 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1742 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1743 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1744 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1745 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1746 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1747 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1748 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1749 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1750 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1751 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1757 public class OpcodeCast : EmptyCast {
1761 public OpcodeCast (Expression child, Type return_type, OpCode op)
1762 : base (child, return_type)
1766 second_valid = false;
1769 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1770 : base (child, return_type)
1775 second_valid = true;
1778 public override Expression DoResolve (EmitContext ec)
1780 // This should never be invoked, we are born in fully
1781 // initialized state.
1786 public override void Emit (EmitContext ec)
1797 /// This kind of cast is used to encapsulate a child and cast it
1798 /// to the class requested
1800 public class ClassCast : EmptyCast {
1801 public ClassCast (Expression child, Type return_type)
1802 : base (child, return_type)
1807 public override Expression DoResolve (EmitContext ec)
1809 // This should never be invoked, we are born in fully
1810 // initialized state.
1815 public override void Emit (EmitContext ec)
1819 if (child.Type.IsGenericParameter)
1820 ec.ig.Emit (OpCodes.Box, child.Type);
1822 if (type.IsGenericParameter)
1823 ec.ig.Emit (OpCodes.Unbox_Any, type);
1825 ec.ig.Emit (OpCodes.Castclass, type);
1830 /// SimpleName expressions are formed of a single word and only happen at the beginning
1831 /// of a dotted-name.
1833 public class SimpleName : Expression {
1835 public readonly TypeArguments Arguments;
1838 public SimpleName (string name, Location l)
1844 public SimpleName (string name, TypeArguments args, Location l)
1851 public SimpleName (string name, TypeParameter[] type_params, Location l)
1856 Arguments = new TypeArguments (l);
1857 foreach (TypeParameter type_param in type_params)
1858 Arguments.Add (new TypeParameterExpr (type_param, l));
1861 public static string RemoveGenericArity (string name)
1864 StringBuilder sb = new StringBuilder ();
1865 while (start < name.Length) {
1866 int pos = name.IndexOf ('`', start);
1868 sb.Append (name.Substring (start));
1872 sb.Append (name.Substring (start, pos-start));
1875 while ((pos < name.Length) && Char.IsNumber (name [pos]))
1881 return sb.ToString ();
1884 public SimpleName GetMethodGroup ()
1886 return new SimpleName (RemoveGenericArity (Name), Arguments, loc);
1889 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1891 if (ec.IsFieldInitializer)
1892 Report.Error (236, l,
1893 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1896 if (name.LastIndexOf ('.') > 0)
1897 name = name.Substring (name.LastIndexOf ('.') + 1);
1900 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1905 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1907 return resolved_to != null && resolved_to.Type != null &&
1908 resolved_to.Type.Name == Name &&
1909 (ec.DeclSpace.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1912 public override Expression DoResolve (EmitContext ec)
1914 return SimpleNameResolve (ec, null, false);
1917 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1919 return SimpleNameResolve (ec, right_side, false);
1923 public Expression DoResolve (EmitContext ec, bool intermediate)
1925 return SimpleNameResolve (ec, null, intermediate);
1928 private bool IsNestedChild (Type t, Type parent)
1933 while (parent != null) {
1934 parent = TypeManager.DropGenericTypeArguments (parent);
1935 if (TypeManager.IsNestedChildOf (t, parent))
1938 parent = parent.BaseType;
1944 FullNamedExpression ResolveNested (EmitContext ec, Type t)
1946 if (!t.IsGenericTypeDefinition)
1949 DeclSpace ds = ec.DeclSpace;
1950 while (ds != null) {
1951 if (IsNestedChild (t, ds.TypeBuilder))
1960 Type[] gen_params = t.GetGenericArguments ();
1962 int arg_count = Arguments != null ? Arguments.Count : 0;
1964 for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
1965 if (arg_count + ds.CountTypeParameters == gen_params.Length) {
1966 TypeArguments new_args = new TypeArguments (loc);
1967 foreach (TypeParameter param in ds.TypeParameters)
1968 new_args.Add (new TypeParameterExpr (param, loc));
1970 if (Arguments != null)
1971 new_args.Add (Arguments);
1973 return new ConstructedType (t, new_args, loc);
1980 public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
1982 FullNamedExpression fne = ec.DeclSpace.LookupGeneric (Name, loc);
1984 return fne.ResolveAsTypeStep (ec, silent);
1986 int errors = Report.Errors;
1987 fne = ec.DeclSpace.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1990 if (fne.Type == null)
1993 FullNamedExpression nested = ResolveNested (ec, fne.Type);
1995 return nested.ResolveAsTypeStep (ec);
1997 if (Arguments != null) {
1998 ConstructedType ct = new ConstructedType (fne, Arguments, loc);
1999 return ct.ResolveAsTypeStep (ec);
2005 if (silent || errors != Report.Errors)
2008 MemberCore mc = ec.DeclSpace.GetDefinition (Name);
2010 Error_UnexpectedKind (ec, "type", GetMemberType (mc), loc);
2012 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
2018 // TODO: I am still not convinced about this. If someone else will need it
2019 // implement this as virtual property in MemberCore hierarchy
2020 string GetMemberType (MemberCore mc)
2022 if (mc is PropertyBase)
2026 if (mc is FieldBase)
2028 if (mc is MethodCore)
2030 if (mc is EnumMember)
2036 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2042 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2046 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2053 /// 7.5.2: Simple Names.
2055 /// Local Variables and Parameters are handled at
2056 /// parse time, so they never occur as SimpleNames.
2058 /// The `intermediate' flag is used by MemberAccess only
2059 /// and it is used to inform us that it is ok for us to
2060 /// avoid the static check, because MemberAccess might end
2061 /// up resolving the Name as a Type name and the access as
2062 /// a static type access.
2064 /// ie: Type Type; .... { Type.GetType (""); }
2066 /// Type is both an instance variable and a Type; Type.GetType
2067 /// is the static method not an instance method of type.
2069 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2071 Expression e = null;
2074 // Stage 1: Performed by the parser (binding to locals or parameters).
2076 Block current_block = ec.CurrentBlock;
2077 if (current_block != null){
2078 LocalInfo vi = current_block.GetLocalInfo (Name);
2080 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2081 if (right_side != null) {
2082 return var.ResolveLValue (ec, right_side, loc);
2084 ResolveFlags rf = ResolveFlags.VariableOrValue;
2086 rf |= ResolveFlags.DisableFlowAnalysis;
2087 return var.Resolve (ec, rf);
2091 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
2093 if (right_side != null)
2094 return pref.ResolveLValue (ec, right_side, loc);
2096 return pref.Resolve (ec);
2101 // Stage 2: Lookup members
2104 DeclSpace lookup_ds = ec.DeclSpace;
2105 Type almost_matched_type = null;
2106 ArrayList almost_matched = null;
2108 if (lookup_ds.TypeBuilder == null)
2111 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
2115 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2116 almost_matched_type = lookup_ds.TypeBuilder;
2117 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2120 lookup_ds =lookup_ds.Parent;
2121 } while (lookup_ds != null);
2123 if (e == null && ec.ContainerType != null)
2124 e = MemberLookup (ec, ec.ContainerType, Name, loc);
2127 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2128 almost_matched_type = ec.ContainerType;
2129 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2131 e = ResolveAsTypeStep (ec, true);
2135 if (almost_matched != null)
2136 almostMatchedMembers = almost_matched;
2137 if (almost_matched_type == null)
2138 almost_matched_type = ec.ContainerType;
2139 MemberLookupFailed (ec, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclSpace.Name, true, loc);
2146 if (e is MemberExpr) {
2147 MemberExpr me = (MemberExpr) e;
2150 if (me.IsInstance) {
2151 if (ec.IsStatic || ec.IsFieldInitializer) {
2153 // Note that an MemberExpr can be both IsInstance and IsStatic.
2154 // An unresolved MethodGroupExpr can contain both kinds of methods
2155 // and each predicate is true if the MethodGroupExpr contains
2156 // at least one of that kind of method.
2160 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2161 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2162 return EmptyExpression.Null;
2166 // Pass the buck to MemberAccess and Invocation.
2168 left = EmptyExpression.Null;
2170 left = ec.GetThis (loc);
2173 left = new TypeExpression (ec.ContainerType, loc);
2176 e = me.ResolveMemberAccess (ec, left, loc, null);
2180 me = e as MemberExpr;
2184 if (Arguments != null) {
2185 MethodGroupExpr mg = me as MethodGroupExpr;
2189 return mg.ResolveGeneric (ec, Arguments);
2193 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2194 me.InstanceExpression.Type != me.DeclaringType &&
2195 !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2196 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2197 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2198 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2202 return (right_side != null)
2203 ? me.DoResolveLValue (ec, right_side)
2204 : me.DoResolve (ec);
2210 public override void Emit (EmitContext ec)
2213 // If this is ever reached, then we failed to
2214 // find the name as a namespace
2217 Error (103, "The name `" + Name +
2218 "' does not exist in the class `" +
2219 ec.DeclSpace.Name + "'");
2222 public override string ToString ()
2227 public override string GetSignatureForError ()
2234 /// Represents a namespace or a type. The name of the class was inspired by
2235 /// section 10.8.1 (Fully Qualified Names).
2237 public abstract class FullNamedExpression : Expression {
2238 public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
2243 public abstract string FullName {
2249 /// Expression that evaluates to a type
2251 public abstract class TypeExpr : FullNamedExpression {
2252 override public FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
2254 TypeExpr t = DoResolveAsTypeStep (ec);
2258 eclass = ExprClass.Type;
2262 override public Expression DoResolve (EmitContext ec)
2264 return ResolveAsTypeTerminal (ec);
2267 override public void Emit (EmitContext ec)
2269 throw new Exception ("Should never be called");
2272 public virtual bool CheckAccessLevel (DeclSpace ds)
2274 return ds.CheckAccessLevel (Type);
2277 public virtual bool AsAccessible (DeclSpace ds, int flags)
2279 return ds.AsAccessible (Type, flags);
2282 public virtual bool IsClass {
2283 get { return Type.IsClass; }
2286 public virtual bool IsValueType {
2287 get { return Type.IsValueType; }
2290 public virtual bool IsInterface {
2291 get { return Type.IsInterface; }
2294 public virtual bool IsSealed {
2295 get { return Type.IsSealed; }
2298 public virtual bool CanInheritFrom ()
2300 if (Type == TypeManager.enum_type ||
2301 (Type == TypeManager.value_type && RootContext.StdLib) ||
2302 Type == TypeManager.multicast_delegate_type ||
2303 Type == TypeManager.delegate_type ||
2304 Type == TypeManager.array_type)
2310 protected abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
2312 public Type ResolveType (EmitContext ec)
2314 TypeExpr t = ResolveAsTypeTerminal (ec);
2318 if (ec.TestObsoleteMethodUsage) {
2319 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (t.Type);
2320 if (obsolete_attr != null) {
2321 AttributeTester.Report_ObsoleteMessage (obsolete_attr, Name, Location);
2328 public abstract string Name {
2332 public override bool Equals (object obj)
2334 TypeExpr tobj = obj as TypeExpr;
2338 return Type == tobj.Type;
2341 public override int GetHashCode ()
2343 return Type.GetHashCode ();
2346 public override string ToString ()
2353 /// Fully resolved Expression that already evaluated to a type
2355 public class TypeExpression : TypeExpr {
2356 public TypeExpression (Type t, Location l)
2359 eclass = ExprClass.Type;
2363 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2368 public override string Name {
2369 get { return Type.ToString (); }
2372 public override string FullName {
2373 get { return Type.FullName; }
2378 /// Used to create types from a fully qualified name. These are just used
2379 /// by the parser to setup the core types. A TypeLookupExpression is always
2380 /// classified as a type.
2382 public class TypeLookupExpression : TypeExpr {
2385 public TypeLookupExpression (string name)
2390 static readonly char [] dot_array = { '.' };
2391 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2396 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2398 string lookup_name = name;
2399 int pos = name.IndexOf ('.');
2401 rest = name.Substring (pos + 1);
2402 lookup_name = name.Substring (0, pos);
2405 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclSpace, lookup_name, Location.Null);
2407 if (resolved != null && rest != null) {
2408 // Now handle the rest of the the name.
2409 string [] elements = rest.Split (dot_array);
2411 int count = elements.Length;
2413 while (i < count && resolved != null && resolved is Namespace) {
2414 Namespace ns = resolved as Namespace;
2415 element = elements [i++];
2416 lookup_name += "." + element;
2417 resolved = ns.Lookup (ec.DeclSpace, element, Location.Null);
2420 if (resolved != null && resolved is TypeExpr) {
2421 Type t = ((TypeExpr) resolved).Type;
2423 if (!ec.DeclSpace.CheckAccessLevel (t)) {
2425 lookup_name = t.FullName;
2432 t = TypeManager.GetNestedType (t, elements [i++]);
2437 if (resolved == null) {
2438 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2442 if (!(resolved is TypeExpr)) {
2443 resolved.Error_UnexpectedKind (ec, "type", loc);
2447 type = ((TypeExpr) resolved).ResolveType (ec);
2451 public override string Name {
2452 get { return name; }
2455 public override string FullName {
2456 get { return name; }
2461 /// Represents an "unbound generic type", ie. typeof (Foo<>).
2464 public class UnboundTypeExpression : TypeExpr
2468 public UnboundTypeExpression (MemberName name, Location l)
2474 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2477 if (name.Left != null) {
2478 Expression lexpr = name.Left.GetTypeExpression ();
2479 expr = new MemberAccess (lexpr, name.Basename, loc);
2481 expr = new SimpleName (name.Basename, loc);
2484 FullNamedExpression fne = expr.ResolveAsTypeStep (ec);
2489 return new TypeExpression (type, loc);
2492 public override string Name {
2493 get { return name.FullName; }
2496 public override string FullName {
2497 get { return name.FullName; }
2501 public class TypeAliasExpression : TypeExpr {
2502 FullNamedExpression alias;
2507 public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
2513 eclass = ExprClass.Type;
2515 name = alias.FullName + "<" + args.ToString () + ">";
2517 name = alias.FullName;
2520 public override string Name {
2521 get { return alias.FullName; }
2524 public override string FullName {
2525 get { return name; }
2528 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2530 texpr = alias.ResolveAsTypeTerminal (ec);
2534 Type type = texpr.ResolveType (ec);
2535 int num_args = TypeManager.GetNumberOfTypeArguments (type);
2538 if (num_args == 0) {
2539 Report.Error (308, loc,
2540 "The non-generic type `{0}' cannot " +
2541 "be used with type arguments.",
2542 TypeManager.CSharpName (type));
2546 ConstructedType ctype = new ConstructedType (type, args, loc);
2547 return ctype.ResolveAsTypeTerminal (ec);
2548 } else if (num_args > 0) {
2549 Report.Error (305, loc,
2550 "Using the generic type `{0}' " +
2551 "requires {1} type arguments",
2552 TypeManager.CSharpName (type), num_args.ToString ());
2556 return new TypeExpression (type, loc);
2559 public override bool CheckAccessLevel (DeclSpace ds)
2561 return texpr.CheckAccessLevel (ds);
2564 public override bool AsAccessible (DeclSpace ds, int flags)
2566 return texpr.AsAccessible (ds, flags);
2569 public override bool IsClass {
2570 get { return texpr.IsClass; }
2573 public override bool IsValueType {
2574 get { return texpr.IsValueType; }
2577 public override bool IsInterface {
2578 get { return texpr.IsInterface; }
2581 public override bool IsSealed {
2582 get { return texpr.IsSealed; }
2587 /// This class denotes an expression which evaluates to a member
2588 /// of a struct or a class.
2590 public abstract class MemberExpr : Expression
2593 /// The name of this member.
2595 public abstract string Name {
2600 /// Whether this is an instance member.
2602 public abstract bool IsInstance {
2607 /// Whether this is a static member.
2609 public abstract bool IsStatic {
2614 /// The type which declares this member.
2616 public abstract Type DeclaringType {
2621 /// The instance expression associated with this member, if it's a
2622 /// non-static member.
2624 public Expression InstanceExpression;
2626 public static void error176 (Location loc, string name)
2628 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2629 "with an instance reference, qualify it with a type name instead", name);
2632 protected bool CheckIntermediateModification ()
2634 if (!InstanceExpression.Type.IsValueType)
2637 if (InstanceExpression is UnboxCast) {
2638 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
2642 if (!(InstanceExpression is IMemoryLocation)) {
2643 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
2644 InstanceExpression.GetSignatureForError ());
2651 // TODO: possible optimalization
2652 // Cache resolved constant result in FieldBuilder <-> expression map
2653 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2654 SimpleName original)
2658 // original == null || original.Resolve (...) ==> left
2661 if (left is TypeExpr) {
2663 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2671 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2674 error176 (loc, GetSignatureForError ());
2678 InstanceExpression = left;
2683 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2688 if (InstanceExpression == EmptyExpression.Null) {
2689 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2693 if (InstanceExpression.Type.IsValueType) {
2694 if (InstanceExpression is IMemoryLocation) {
2695 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2697 LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
2698 InstanceExpression.Emit (ec);
2700 t.AddressOf (ec, AddressOp.Store);
2703 InstanceExpression.Emit (ec);
2705 if (prepare_for_load)
2706 ec.ig.Emit (OpCodes.Dup);
2711 /// MethodGroup Expression.
2713 /// This is a fully resolved expression that evaluates to a type
2715 public class MethodGroupExpr : MemberExpr {
2716 public MethodBase [] Methods;
2717 bool has_type_arguments = false;
2718 bool identical_type_name = false;
2721 public MethodGroupExpr (MemberInfo [] mi, Location l)
2723 Methods = new MethodBase [mi.Length];
2724 mi.CopyTo (Methods, 0);
2725 eclass = ExprClass.MethodGroup;
2726 type = TypeManager.object_type;
2730 public MethodGroupExpr (ArrayList list, Location l)
2732 Methods = new MethodBase [list.Count];
2735 list.CopyTo (Methods, 0);
2737 foreach (MemberInfo m in list){
2738 if (!(m is MethodBase)){
2739 Console.WriteLine ("Name " + m.Name);
2740 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2747 eclass = ExprClass.MethodGroup;
2748 type = TypeManager.object_type;
2751 public override Type DeclaringType {
2754 // We assume that the top-level type is in the end
2756 return Methods [Methods.Length - 1].DeclaringType;
2757 //return Methods [0].DeclaringType;
2761 public bool HasTypeArguments {
2763 return has_type_arguments;
2767 has_type_arguments = value;
2771 public bool IdenticalTypeName {
2773 return identical_type_name;
2777 identical_type_name = value;
2781 public bool IsBase {
2790 public override string GetSignatureForError ()
2792 return TypeManager.CSharpSignature (Methods [0]);
2795 public override string Name {
2797 return Methods [0].Name;
2801 public override bool IsInstance {
2803 foreach (MethodBase mb in Methods)
2811 public override bool IsStatic {
2813 foreach (MethodBase mb in Methods)
2821 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2822 SimpleName original)
2824 if (!(left is TypeExpr) &&
2825 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2826 IdenticalTypeName = true;
2828 return base.ResolveMemberAccess (ec, left, loc, original);
2831 override public Expression DoResolve (EmitContext ec)
2834 InstanceExpression = null;
2836 if (InstanceExpression != null) {
2837 InstanceExpression = InstanceExpression.DoResolve (ec);
2838 if (InstanceExpression == null)
2845 public void ReportUsageError ()
2847 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2848 Name + "()' is referenced without parentheses");
2851 override public void Emit (EmitContext ec)
2853 ReportUsageError ();
2856 bool RemoveMethods (bool keep_static)
2858 ArrayList smethods = new ArrayList ();
2860 foreach (MethodBase mb in Methods){
2861 if (mb.IsStatic == keep_static)
2865 if (smethods.Count == 0)
2868 Methods = new MethodBase [smethods.Count];
2869 smethods.CopyTo (Methods, 0);
2875 /// Removes any instance methods from the MethodGroup, returns
2876 /// false if the resulting set is empty.
2878 public bool RemoveInstanceMethods ()
2880 return RemoveMethods (true);
2884 /// Removes any static methods from the MethodGroup, returns
2885 /// false if the resulting set is empty.
2887 public bool RemoveStaticMethods ()
2889 return RemoveMethods (false);
2892 public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
2894 if (args.Resolve (ec) == false)
2897 Type[] atypes = args.Arguments;
2899 int first_count = 0;
2900 MethodInfo first = null;
2902 ArrayList list = new ArrayList ();
2903 foreach (MethodBase mb in Methods) {
2904 MethodInfo mi = mb as MethodInfo;
2905 if ((mi == null) || !mi.HasGenericParameters)
2908 Type[] gen_params = mi.GetGenericArguments ();
2910 if (first == null) {
2912 first_count = gen_params.Length;
2915 if (gen_params.Length != atypes.Length)
2918 list.Add (mi.MakeGenericMethod (atypes));
2921 if (list.Count > 0) {
2922 MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
2923 new_mg.InstanceExpression = InstanceExpression;
2924 new_mg.HasTypeArguments = true;
2930 305, loc, "Using the generic method `{0}' " +
2931 "requires {1} type arguments", Name,
2932 first_count.ToString ());
2935 308, loc, "The non-generic method `{0}' " +
2936 "cannot be used with type arguments", Name);
2943 /// Fully resolved expression that evaluates to a Field
2945 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2946 public readonly FieldInfo FieldInfo;
2947 VariableInfo variable_info;
2949 LocalTemporary temp;
2951 bool in_initializer;
2953 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2956 this.in_initializer = in_initializer;
2959 public FieldExpr (FieldInfo fi, Location l)
2962 eclass = ExprClass.Variable;
2963 type = TypeManager.TypeToCoreType (fi.FieldType);
2967 public override string Name {
2969 return FieldInfo.Name;
2973 public override bool IsInstance {
2975 return !FieldInfo.IsStatic;
2979 public override bool IsStatic {
2981 return FieldInfo.IsStatic;
2985 public override Type DeclaringType {
2987 return FieldInfo.DeclaringType;
2991 public override string GetSignatureForError ()
2993 return TypeManager.GetFullNameSignature (FieldInfo);
2996 public VariableInfo VariableInfo {
2998 return variable_info;
3002 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3003 SimpleName original)
3005 FieldInfo fi = FieldInfo.Mono_GetGenericFieldDefinition ();
3007 Type t = fi.FieldType;
3009 if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
3010 IConstant ic = TypeManager.GetConstant (fi);
3013 ic = new ExternalConstant (fi);
3015 ic = ExternalConstant.CreateDecimal (fi);
3017 return base.ResolveMemberAccess (ec, left, loc, original);
3020 TypeManager.RegisterConstant (fi, ic);
3023 bool left_is_type = left is TypeExpr;
3024 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
3025 Report.SymbolRelatedToPreviousError (FieldInfo);
3026 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
3030 if (ic.ResolveValue ()) {
3031 if (ec.TestObsoleteMethodUsage)
3032 ic.CheckObsoleteness (loc);
3038 if (t.IsPointer && !ec.InUnsafe) {
3043 return base.ResolveMemberAccess (ec, left, loc, original);
3046 override public Expression DoResolve (EmitContext ec)
3048 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
3049 if (FieldInfo.FieldType is TypeBuilder) {
3050 if (FieldInfo.IsStatic)
3051 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
3052 GetSignatureForError ());
3054 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
3055 TypeManager.CSharpName (DeclaringType), Name);
3057 if (FieldInfo.IsStatic)
3058 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
3061 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
3067 if (!FieldInfo.IsStatic){
3068 if (InstanceExpression == null){
3070 // This can happen when referencing an instance field using
3071 // a fully qualified type expression: TypeName.InstanceField = xxx
3073 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
3077 // Resolve the field's instance expression while flow analysis is turned
3078 // off: when accessing a field "a.b", we must check whether the field
3079 // "a.b" is initialized, not whether the whole struct "a" is initialized.
3080 InstanceExpression = InstanceExpression.Resolve (
3081 ec, ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis);
3082 if (InstanceExpression == null)
3086 if (!in_initializer && !ec.IsFieldInitializer) {
3087 ObsoleteAttribute oa;
3088 FieldBase f = TypeManager.GetField (FieldInfo);
3090 if (ec.TestObsoleteMethodUsage)
3091 f.CheckObsoleteness (loc);
3092 // To be sure that type is external because we do not register generated fields
3093 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
3094 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
3096 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
3100 AnonymousContainer am = ec.CurrentAnonymousMethod;
3102 if (!FieldInfo.IsStatic){
3103 if (!am.IsIterator && (ec.TypeContainer is Struct)){
3104 Report.Error (1673, loc,
3105 "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",
3109 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
3110 ec.CaptureField (this);
3114 // If the instance expression is a local variable or parameter.
3115 IVariable var = InstanceExpression as IVariable;
3116 if ((var == null) || (var.VariableInfo == null))
3119 VariableInfo vi = var.VariableInfo;
3120 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
3123 variable_info = vi.GetSubStruct (FieldInfo.Name);
3127 void Report_AssignToReadonly (bool is_instance)
3132 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
3134 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
3136 Report.Error (is_instance ? 191 : 198, loc, msg);
3139 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3141 IVariable var = InstanceExpression as IVariable;
3142 if ((var != null) && (var.VariableInfo != null))
3143 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
3145 Expression e = DoResolve (ec);
3150 if (!FieldInfo.IsStatic && !CheckIntermediateModification ())
3153 FieldBase fb = TypeManager.GetField (FieldInfo);
3157 if (!FieldInfo.IsInitOnly)
3161 // InitOnly fields can only be assigned in constructors
3164 if (ec.IsConstructor){
3165 if (IsStatic && !ec.IsStatic)
3166 Report_AssignToReadonly (false);
3169 if (ec.TypeContainer.CurrentType != null)
3170 ctype = ec.TypeContainer.CurrentType;
3172 ctype = ec.ContainerType;
3174 if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
3178 Report_AssignToReadonly (!IsStatic);
3183 public override void CheckMarshallByRefAccess (Type container)
3185 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
3186 Report.SymbolRelatedToPreviousError (DeclaringType);
3187 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",
3188 GetSignatureForError ());
3192 public bool VerifyFixed ()
3194 IVariable variable = InstanceExpression as IVariable;
3195 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
3196 // We defer the InstanceExpression check after the variable check to avoid a
3197 // separate null check on InstanceExpression.
3198 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
3201 public override int GetHashCode()
3203 return FieldInfo.GetHashCode ();
3206 public override bool Equals (object obj)
3208 FieldExpr fe = obj as FieldExpr;
3212 if (FieldInfo != fe.FieldInfo)
3215 if (InstanceExpression == null || fe.InstanceExpression == null)
3218 return InstanceExpression.Equals (fe.InstanceExpression);
3221 public void Emit (EmitContext ec, bool leave_copy)
3223 ILGenerator ig = ec.ig;
3224 bool is_volatile = false;
3226 FieldInfo the_fi = FieldInfo.Mono_GetGenericFieldDefinition ();
3227 if (the_fi is FieldBuilder){
3228 FieldBase f = TypeManager.GetField (the_fi);
3230 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3233 f.SetMemberIsUsed ();
3237 if (FieldInfo.IsStatic){
3239 ig.Emit (OpCodes.Volatile);
3241 ig.Emit (OpCodes.Ldsfld, FieldInfo);
3244 EmitInstance (ec, false);
3247 ig.Emit (OpCodes.Volatile);
3249 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
3252 ig.Emit (OpCodes.Ldflda, FieldInfo);
3253 ig.Emit (OpCodes.Ldflda, ff.Element);
3256 ig.Emit (OpCodes.Ldfld, FieldInfo);
3261 ec.ig.Emit (OpCodes.Dup);
3262 if (!FieldInfo.IsStatic) {
3263 temp = new LocalTemporary (ec, this.Type);
3269 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3271 FieldAttributes fa = FieldInfo.Attributes;
3272 bool is_static = (fa & FieldAttributes.Static) != 0;
3273 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3274 ILGenerator ig = ec.ig;
3275 prepared = prepare_for_load;
3277 if (is_readonly && !ec.IsConstructor){
3278 Report_AssignToReadonly (!is_static);
3282 EmitInstance (ec, prepare_for_load);
3286 ec.ig.Emit (OpCodes.Dup);
3287 if (!FieldInfo.IsStatic) {
3288 temp = new LocalTemporary (ec, this.Type);
3293 if (FieldInfo is FieldBuilder){
3294 FieldBase f = TypeManager.GetField (FieldInfo);
3296 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3297 ig.Emit (OpCodes.Volatile);
3304 ig.Emit (OpCodes.Stsfld, FieldInfo);
3306 ig.Emit (OpCodes.Stfld, FieldInfo);
3312 public override void Emit (EmitContext ec)
3317 public void AddressOf (EmitContext ec, AddressOp mode)
3319 ILGenerator ig = ec.ig;
3321 if (FieldInfo is FieldBuilder){
3322 FieldBase f = TypeManager.GetField (FieldInfo);
3324 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3325 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3326 f.GetSignatureForError ());
3330 if ((mode & AddressOp.Store) != 0)
3332 if ((mode & AddressOp.Load) != 0)
3333 f.SetMemberIsUsed ();
3338 // Handle initonly fields specially: make a copy and then
3339 // get the address of the copy.
3342 if (FieldInfo.IsInitOnly){
3344 if (ec.IsConstructor){
3345 if (FieldInfo.IsStatic){
3357 local = ig.DeclareLocal (type);
3358 ig.Emit (OpCodes.Stloc, local);
3359 ig.Emit (OpCodes.Ldloca, local);
3364 if (FieldInfo.IsStatic){
3365 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3367 EmitInstance (ec, false);
3368 ig.Emit (OpCodes.Ldflda, FieldInfo);
3374 // A FieldExpr whose address can not be taken
3376 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3377 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3381 public new void AddressOf (EmitContext ec, AddressOp mode)
3383 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3388 /// Expression that evaluates to a Property. The Assign class
3389 /// might set the `Value' expression if we are in an assignment.
3391 /// This is not an LValue because we need to re-write the expression, we
3392 /// can not take data from the stack and store it.
3394 public class PropertyExpr : MemberExpr, IAssignMethod {
3395 public readonly PropertyInfo PropertyInfo;
3398 // This is set externally by the `BaseAccess' class
3401 MethodInfo getter, setter;
3406 LocalTemporary temp;
3409 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3411 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
3414 eclass = ExprClass.PropertyAccess;
3418 type = TypeManager.TypeToCoreType (pi.PropertyType);
3420 ResolveAccessors (ec);
3423 public override string Name {
3425 return PropertyInfo.Name;
3429 public override bool IsInstance {
3435 public override bool IsStatic {
3441 public override Type DeclaringType {
3443 return PropertyInfo.DeclaringType;
3447 public override string GetSignatureForError ()
3449 return TypeManager.GetFullNameSignature (PropertyInfo);
3452 void FindAccessors (Type invocation_type)
3454 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3455 BindingFlags.Static | BindingFlags.Instance |
3456 BindingFlags.DeclaredOnly;
3458 Type current = PropertyInfo.DeclaringType;
3459 for (; current != null; current = current.BaseType) {
3460 MemberInfo[] group = TypeManager.MemberLookup (
3461 invocation_type, invocation_type, current,
3462 MemberTypes.Property, flags, PropertyInfo.Name, null);
3467 if (group.Length != 1)
3468 // Oooops, can this ever happen ?
3471 PropertyInfo pi = (PropertyInfo) group [0];
3474 getter = pi.GetGetMethod (true);
3477 setter = pi.GetSetMethod (true);
3479 MethodInfo accessor = getter != null ? getter : setter;
3481 if (!accessor.IsVirtual)
3487 // We also perform the permission checking here, as the PropertyInfo does not
3488 // hold the information for the accessibility of its setter/getter
3490 void ResolveAccessors (EmitContext ec)
3492 FindAccessors (ec.ContainerType);
3494 if (getter != null) {
3495 MethodInfo the_getter = getter;
3496 if (the_getter.Mono_IsInflatedMethod)
3497 the_getter = the_getter.GetGenericMethodDefinition ();
3498 IMethodData md = TypeManager.GetMethod (the_getter);
3500 md.SetMemberIsUsed ();
3502 AccessorTable [getter] = PropertyInfo;
3503 is_static = getter.IsStatic;
3506 if (setter != null) {
3507 MethodInfo the_setter = setter;
3508 if (the_setter.Mono_IsInflatedMethod)
3509 the_setter = the_setter.GetGenericMethodDefinition ();
3510 IMethodData md = TypeManager.GetMethod (the_setter);
3512 md.SetMemberIsUsed ();
3514 AccessorTable [setter] = PropertyInfo;
3515 is_static = setter.IsStatic;
3519 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3522 InstanceExpression = null;
3526 if (InstanceExpression == null) {
3527 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3531 InstanceExpression = InstanceExpression.DoResolve (ec);
3532 if (InstanceExpression == null)
3535 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3537 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3538 InstanceExpression.Type != ec.ContainerType &&
3539 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3540 InstanceExpression.Type.IsSubclassOf (PropertyInfo.DeclaringType)) {
3541 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3548 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3550 // TODO: correctly we should compare arguments but it will lead to bigger changes
3551 if (mi is MethodBuilder) {
3552 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3556 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3558 ParameterData iparams = TypeManager.GetParameterData (mi);
3559 sig.Append (getter ? "get_" : "set_");
3561 sig.Append (iparams.GetSignatureForError ());
3563 Report.SymbolRelatedToPreviousError (mi);
3564 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3565 Name, sig.ToString ());
3568 override public Expression DoResolve (EmitContext ec)
3573 if (getter != null){
3574 if (TypeManager.GetParameterData (getter).Count != 0){
3575 Error_PropertyNotFound (getter, true);
3580 if (getter == null){
3582 // The following condition happens if the PropertyExpr was
3583 // created, but is invalid (ie, the property is inaccessible),
3584 // and we did not want to embed the knowledge about this in
3585 // the caller routine. This only avoids double error reporting.
3590 if (InstanceExpression != EmptyExpression.Null) {
3591 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3592 TypeManager.GetFullNameSignature (PropertyInfo));
3597 bool must_do_cs1540_check = false;
3598 if (getter != null &&
3599 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3600 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3601 if (pm != null && pm.HasCustomAccessModifier) {
3602 Report.SymbolRelatedToPreviousError (pm);
3603 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3604 TypeManager.CSharpSignature (getter));
3607 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3611 if (!InstanceResolve (ec, must_do_cs1540_check))
3615 // Only base will allow this invocation to happen.
3617 if (IsBase && getter.IsAbstract) {
3618 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3622 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3632 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3634 if (setter == null){
3636 // The following condition happens if the PropertyExpr was
3637 // created, but is invalid (ie, the property is inaccessible),
3638 // and we did not want to embed the knowledge about this in
3639 // the caller routine. This only avoids double error reporting.
3644 Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)",
3645 TypeManager.GetFullNameSignature (PropertyInfo));
3649 if (TypeManager.GetParameterData (setter).Count != 1){
3650 Error_PropertyNotFound (setter, false);
3654 bool must_do_cs1540_check;
3655 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3656 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3657 if (pm != null && pm.HasCustomAccessModifier) {
3658 Report.SymbolRelatedToPreviousError (pm);
3659 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3660 TypeManager.CSharpSignature (setter));
3663 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3667 if (!InstanceResolve (ec, must_do_cs1540_check))
3671 // Only base will allow this invocation to happen.
3673 if (IsBase && setter.IsAbstract){
3674 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3679 // Check that we are not making changes to a temporary memory location
3681 if (InstanceExpression != null && !CheckIntermediateModification ())
3687 public override void Emit (EmitContext ec)
3692 public void Emit (EmitContext ec, bool leave_copy)
3695 // Special case: length of single dimension array property is turned into ldlen
3697 if ((getter == TypeManager.system_int_array_get_length) ||
3698 (getter == TypeManager.int_array_get_length)){
3699 Type iet = InstanceExpression.Type;
3702 // System.Array.Length can be called, but the Type does not
3703 // support invoking GetArrayRank, so test for that case first
3705 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3707 EmitInstance (ec, false);
3708 ec.ig.Emit (OpCodes.Ldlen);
3709 ec.ig.Emit (OpCodes.Conv_I4);
3714 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3717 ec.ig.Emit (OpCodes.Dup);
3719 temp = new LocalTemporary (ec, this.Type);
3726 // Implements the IAssignMethod interface for assignments
3728 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3730 Expression my_source = source;
3732 prepared = prepare_for_load;
3737 ec.ig.Emit (OpCodes.Dup);
3739 temp = new LocalTemporary (ec, this.Type);
3743 } else if (leave_copy) {
3746 temp = new LocalTemporary (ec, this.Type);
3752 ArrayList args = new ArrayList (1);
3753 args.Add (new Argument (my_source, Argument.AType.Expression));
3755 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3763 /// Fully resolved expression that evaluates to an Event
3765 public class EventExpr : MemberExpr {
3766 public readonly EventInfo EventInfo;
3769 MethodInfo add_accessor, remove_accessor;
3771 public EventExpr (EventInfo ei, Location loc)
3775 eclass = ExprClass.EventAccess;
3777 add_accessor = TypeManager.GetAddMethod (ei);
3778 remove_accessor = TypeManager.GetRemoveMethod (ei);
3780 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3783 if (EventInfo is MyEventBuilder){
3784 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3785 type = eb.EventType;
3788 type = EventInfo.EventHandlerType;
3791 public override string Name {
3793 return EventInfo.Name;
3797 public override bool IsInstance {
3803 public override bool IsStatic {
3809 public override Type DeclaringType {
3811 return EventInfo.DeclaringType;
3815 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3816 SimpleName original)
3819 // If the event is local to this class, we transform ourselves into a FieldExpr
3822 if (EventInfo.DeclaringType == ec.ContainerType ||
3823 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3824 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3827 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc);
3830 Report.Error (-200, loc, "Internal error!!");
3834 InstanceExpression = null;
3836 return ml.ResolveMemberAccess (ec, left, loc, original);
3840 return base.ResolveMemberAccess (ec, left, loc, original);
3844 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3847 InstanceExpression = null;
3851 if (InstanceExpression == null) {
3852 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3856 InstanceExpression = InstanceExpression.DoResolve (ec);
3857 if (InstanceExpression == null)
3861 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3862 // However, in the Event case, we reported a CS0122 instead.
3864 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) {
3865 if ((InstanceExpression.Type != ec.ContainerType) &&
3866 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3867 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3875 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3877 return DoResolve (ec);
3880 public override Expression DoResolve (EmitContext ec)
3882 bool must_do_cs1540_check;
3883 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3884 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3885 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3889 if (!InstanceResolve (ec, must_do_cs1540_check))
3895 public override void Emit (EmitContext ec)
3897 if (InstanceExpression is This)
3898 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3900 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3901 "(except on the defining type)", Name);
3904 public override string GetSignatureForError ()
3906 return TypeManager.CSharpSignature (EventInfo);
3909 public void EmitAddOrRemove (EmitContext ec, Expression source)
3911 BinaryDelegate source_del = (BinaryDelegate) source;
3912 Expression handler = source_del.Right;
3914 Argument arg = new Argument (handler, Argument.AType.Expression);
3915 ArrayList args = new ArrayList ();
3919 if (source_del.IsAddition)
3920 Invocation.EmitCall (
3921 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3923 Invocation.EmitCall (
3924 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3929 public class TemporaryVariable : Expression, IMemoryLocation
3933 public TemporaryVariable (Type type, Location loc)
3937 eclass = ExprClass.Value;
3940 public override Expression DoResolve (EmitContext ec)
3945 TypeExpr te = new TypeExpression (type, loc);
3946 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3947 if (!li.Resolve (ec))
3950 AnonymousContainer am = ec.CurrentAnonymousMethod;
3951 if ((am != null) && am.IsIterator)
3952 ec.CaptureVariable (li);
3957 public override void Emit (EmitContext ec)
3959 ILGenerator ig = ec.ig;
3961 if (li.FieldBuilder != null) {
3962 ig.Emit (OpCodes.Ldarg_0);
3963 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3965 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3969 public void EmitLoadAddress (EmitContext ec)
3971 ILGenerator ig = ec.ig;
3973 if (li.FieldBuilder != null) {
3974 ig.Emit (OpCodes.Ldarg_0);
3975 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3977 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3981 public void Store (EmitContext ec, Expression right_side)
3983 if (li.FieldBuilder != null)
3984 ec.ig.Emit (OpCodes.Ldarg_0);
3986 right_side.Emit (ec);
3987 if (li.FieldBuilder != null) {
3988 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3990 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3994 public void EmitThis (EmitContext ec)
3996 if (li.FieldBuilder != null) {
3997 ec.ig.Emit (OpCodes.Ldarg_0);
4001 public void EmitStore (ILGenerator ig)
4003 if (li.FieldBuilder != null)
4004 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
4006 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
4009 public void AddressOf (EmitContext ec, AddressOp mode)
4011 EmitLoadAddress (ec);