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);
419 Constant c = e as Constant;
423 EmptyCast empty = e as EmptyCast;
425 c = empty.Child as Constant;
427 // 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, String.Format ("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 {
1328 throw new NotImplementedException ();
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 if (parent.IsGenericInstance)
1935 parent = parent.GetGenericTypeDefinition ();
1937 if (TypeManager.IsNestedChildOf (t, parent))
1940 parent = parent.BaseType;
1946 FullNamedExpression ResolveNested (EmitContext ec, Type t)
1948 if (!t.IsGenericTypeDefinition)
1951 DeclSpace ds = ec.DeclSpace;
1952 while (ds != null) {
1953 if (IsNestedChild (t, ds.TypeBuilder))
1962 Type[] gen_params = t.GetGenericArguments ();
1964 int arg_count = Arguments != null ? Arguments.Count : 0;
1966 for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
1967 if (arg_count + ds.CountTypeParameters == gen_params.Length) {
1968 TypeArguments new_args = new TypeArguments (loc);
1969 foreach (TypeParameter param in ds.TypeParameters)
1970 new_args.Add (new TypeParameterExpr (param, loc));
1972 if (Arguments != null)
1973 new_args.Add (Arguments);
1975 return new ConstructedType (t, new_args, loc);
1982 public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
1984 FullNamedExpression fne = ec.DeclSpace.LookupGeneric (Name, loc);
1986 return fne.ResolveAsTypeStep (ec, silent);
1988 int errors = Report.Errors;
1989 fne = ec.DeclSpace.LookupType (Name, loc, /*ignore_cs0104=*/ false);
1992 if (fne.Type == null)
1995 FullNamedExpression nested = ResolveNested (ec, fne.Type);
1997 return nested.ResolveAsTypeStep (ec);
1999 if (Arguments != null) {
2000 ConstructedType ct = new ConstructedType (fne, Arguments, loc);
2001 return ct.ResolveAsTypeStep (ec);
2007 if (silent || errors != Report.Errors)
2010 MemberCore mc = ec.DeclSpace.GetDefinition (Name);
2012 Error_UnexpectedKind (ec, "type", GetMemberType (mc), loc);
2014 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
2020 // TODO: I am still not convinced about this. If someone else will need it
2021 // implement this as virtual property in MemberCore hierarchy
2022 string GetMemberType (MemberCore mc)
2024 if (mc is PropertyBase)
2028 if (mc is FieldBase)
2030 if (mc is MethodCore)
2032 if (mc is EnumMember)
2038 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2044 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2048 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2055 /// 7.5.2: Simple Names.
2057 /// Local Variables and Parameters are handled at
2058 /// parse time, so they never occur as SimpleNames.
2060 /// The `intermediate' flag is used by MemberAccess only
2061 /// and it is used to inform us that it is ok for us to
2062 /// avoid the static check, because MemberAccess might end
2063 /// up resolving the Name as a Type name and the access as
2064 /// a static type access.
2066 /// ie: Type Type; .... { Type.GetType (""); }
2068 /// Type is both an instance variable and a Type; Type.GetType
2069 /// is the static method not an instance method of type.
2071 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2073 Expression e = null;
2076 // Stage 1: Performed by the parser (binding to locals or parameters).
2078 Block current_block = ec.CurrentBlock;
2079 if (current_block != null){
2080 LocalInfo vi = current_block.GetLocalInfo (Name);
2082 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2083 if (right_side != null) {
2084 return var.ResolveLValue (ec, right_side, loc);
2086 ResolveFlags rf = ResolveFlags.VariableOrValue;
2088 rf |= ResolveFlags.DisableFlowAnalysis;
2089 return var.Resolve (ec, rf);
2093 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
2095 if (right_side != null)
2096 return pref.ResolveLValue (ec, right_side, loc);
2098 return pref.Resolve (ec);
2103 // Stage 2: Lookup members
2106 DeclSpace lookup_ds = ec.DeclSpace;
2107 Type almost_matched_type = null;
2108 ArrayList almost_matched = null;
2110 if (lookup_ds.TypeBuilder == null)
2113 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
2117 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2118 almost_matched_type = lookup_ds.TypeBuilder;
2119 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2122 lookup_ds =lookup_ds.Parent;
2123 } while (lookup_ds != null);
2125 if (e == null && ec.ContainerType != null)
2126 e = MemberLookup (ec, ec.ContainerType, Name, loc);
2129 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2130 almost_matched_type = ec.ContainerType;
2131 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2133 e = ResolveAsTypeStep (ec, true);
2137 if (almost_matched != null)
2138 almostMatchedMembers = almost_matched;
2139 if (almost_matched_type == null)
2140 almost_matched_type = ec.ContainerType;
2141 MemberLookupFailed (ec, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclSpace.Name, true, loc);
2148 if (e is MemberExpr) {
2149 MemberExpr me = (MemberExpr) e;
2152 if (me.IsInstance) {
2153 if (ec.IsStatic || ec.IsFieldInitializer) {
2155 // Note that an MemberExpr can be both IsInstance and IsStatic.
2156 // An unresolved MethodGroupExpr can contain both kinds of methods
2157 // and each predicate is true if the MethodGroupExpr contains
2158 // at least one of that kind of method.
2162 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2163 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2168 // Pass the buck to MemberAccess and Invocation.
2170 left = EmptyExpression.Null;
2172 left = ec.GetThis (loc);
2175 left = new TypeExpression (ec.ContainerType, loc);
2178 e = me.ResolveMemberAccess (ec, left, loc, null);
2182 me = e as MemberExpr;
2186 if (Arguments != null) {
2187 MethodGroupExpr mg = me as MethodGroupExpr;
2191 return mg.ResolveGeneric (ec, Arguments);
2195 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2196 me.InstanceExpression.Type != me.DeclaringType &&
2197 !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2198 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2199 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2200 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2204 return (right_side != null)
2205 ? me.DoResolveLValue (ec, right_side)
2206 : me.DoResolve (ec);
2212 public override void Emit (EmitContext ec)
2215 // If this is ever reached, then we failed to
2216 // find the name as a namespace
2219 Error (103, "The name `" + Name +
2220 "' does not exist in the class `" +
2221 ec.DeclSpace.Name + "'");
2224 public override string ToString ()
2229 public override string GetSignatureForError ()
2236 /// Represents a namespace or a type. The name of the class was inspired by
2237 /// section 10.8.1 (Fully Qualified Names).
2239 public abstract class FullNamedExpression : Expression {
2240 public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
2245 public abstract string FullName {
2251 /// Expression that evaluates to a type
2253 public abstract class TypeExpr : FullNamedExpression {
2254 override public FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
2256 TypeExpr t = DoResolveAsTypeStep (ec);
2260 eclass = ExprClass.Type;
2264 override public Expression DoResolve (EmitContext ec)
2266 return ResolveAsTypeTerminal (ec);
2269 override public void Emit (EmitContext ec)
2271 throw new Exception ("Should never be called");
2274 public virtual bool CheckAccessLevel (DeclSpace ds)
2276 return ds.CheckAccessLevel (Type);
2279 public virtual bool AsAccessible (DeclSpace ds, int flags)
2281 return ds.AsAccessible (Type, flags);
2284 public virtual bool IsClass {
2285 get { return Type.IsClass; }
2288 public virtual bool IsValueType {
2289 get { return Type.IsValueType; }
2292 public virtual bool IsInterface {
2293 get { return Type.IsInterface; }
2296 public virtual bool IsSealed {
2297 get { return Type.IsSealed; }
2300 public virtual bool CanInheritFrom ()
2302 if (Type == TypeManager.enum_type ||
2303 (Type == TypeManager.value_type && RootContext.StdLib) ||
2304 Type == TypeManager.multicast_delegate_type ||
2305 Type == TypeManager.delegate_type ||
2306 Type == TypeManager.array_type)
2312 protected abstract TypeExpr DoResolveAsTypeStep (EmitContext ec);
2314 public Type ResolveType (EmitContext ec)
2316 TypeExpr t = ResolveAsTypeTerminal (ec);
2320 if (ec.TestObsoleteMethodUsage) {
2321 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (t.Type);
2322 if (obsolete_attr != null) {
2323 AttributeTester.Report_ObsoleteMessage (obsolete_attr, Name, Location);
2330 public abstract string Name {
2334 public override bool Equals (object obj)
2336 TypeExpr tobj = obj as TypeExpr;
2340 return Type == tobj.Type;
2343 public override int GetHashCode ()
2345 return Type.GetHashCode ();
2348 public override string ToString ()
2355 /// Fully resolved Expression that already evaluated to a type
2357 public class TypeExpression : TypeExpr {
2358 public TypeExpression (Type t, Location l)
2361 eclass = ExprClass.Type;
2365 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2370 public override string Name {
2371 get { return Type.ToString (); }
2374 public override string FullName {
2375 get { return Type.FullName; }
2380 /// Used to create types from a fully qualified name. These are just used
2381 /// by the parser to setup the core types. A TypeLookupExpression is always
2382 /// classified as a type.
2384 public class TypeLookupExpression : TypeExpr {
2387 public TypeLookupExpression (string name)
2392 static readonly char [] dot_array = { '.' };
2393 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2398 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2400 string lookup_name = name;
2401 int pos = name.IndexOf ('.');
2403 rest = name.Substring (pos + 1);
2404 lookup_name = name.Substring (0, pos);
2407 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclSpace, lookup_name, Location.Null);
2409 if (resolved != null && rest != null) {
2410 // Now handle the rest of the the name.
2411 string [] elements = rest.Split (dot_array);
2413 int count = elements.Length;
2415 while (i < count && resolved != null && resolved is Namespace) {
2416 Namespace ns = resolved as Namespace;
2417 element = elements [i++];
2418 lookup_name += "." + element;
2419 resolved = ns.Lookup (ec.DeclSpace, element, Location.Null);
2422 if (resolved != null && resolved is TypeExpr) {
2423 Type t = ((TypeExpr) resolved).Type;
2425 if (!ec.DeclSpace.CheckAccessLevel (t)) {
2427 lookup_name = t.FullName;
2434 t = TypeManager.GetNestedType (t, elements [i++]);
2439 if (resolved == null) {
2440 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2444 if (!(resolved is TypeExpr)) {
2445 resolved.Error_UnexpectedKind (ec, "type", loc);
2449 type = ((TypeExpr) resolved).ResolveType (ec);
2453 public override string Name {
2454 get { return name; }
2457 public override string FullName {
2458 get { return name; }
2463 /// Represents an "unbound generic type", ie. typeof (Foo<>).
2466 public class UnboundTypeExpression : TypeExpr
2470 public UnboundTypeExpression (MemberName name, Location l)
2476 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2479 if (name.Left != null) {
2480 Expression lexpr = name.Left.GetTypeExpression ();
2481 expr = new MemberAccess (lexpr, name.Basename, loc);
2483 expr = new SimpleName (name.Basename, loc);
2486 FullNamedExpression fne = expr.ResolveAsTypeStep (ec);
2491 return new TypeExpression (type, loc);
2494 public override string Name {
2495 get { return name.FullName; }
2498 public override string FullName {
2499 get { return name.FullName; }
2503 public class TypeAliasExpression : TypeExpr {
2504 FullNamedExpression alias;
2509 public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
2515 eclass = ExprClass.Type;
2517 name = alias.FullName + "<" + args.ToString () + ">";
2519 name = alias.FullName;
2522 public override string Name {
2523 get { return alias.FullName; }
2526 public override string FullName {
2527 get { return name; }
2530 protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
2532 texpr = alias.ResolveAsTypeTerminal (ec);
2536 Type type = texpr.ResolveType (ec);
2537 int num_args = TypeManager.GetNumberOfTypeArguments (type);
2540 if (num_args == 0) {
2541 Report.Error (308, loc,
2542 "The non-generic type `{0}' cannot " +
2543 "be used with type arguments.",
2544 TypeManager.CSharpName (type));
2548 ConstructedType ctype = new ConstructedType (type, args, loc);
2549 return ctype.ResolveAsTypeTerminal (ec);
2550 } else if (num_args > 0) {
2551 Report.Error (305, loc,
2552 "Using the generic type `{0}' " +
2553 "requires {1} type arguments",
2554 TypeManager.CSharpName (type), num_args.ToString ());
2558 return new TypeExpression (type, loc);
2561 public override bool CheckAccessLevel (DeclSpace ds)
2563 return texpr.CheckAccessLevel (ds);
2566 public override bool AsAccessible (DeclSpace ds, int flags)
2568 return texpr.AsAccessible (ds, flags);
2571 public override bool IsClass {
2572 get { return texpr.IsClass; }
2575 public override bool IsValueType {
2576 get { return texpr.IsValueType; }
2579 public override bool IsInterface {
2580 get { return texpr.IsInterface; }
2583 public override bool IsSealed {
2584 get { return texpr.IsSealed; }
2589 /// This class denotes an expression which evaluates to a member
2590 /// of a struct or a class.
2592 public abstract class MemberExpr : Expression
2595 /// The name of this member.
2597 public abstract string Name {
2602 /// Whether this is an instance member.
2604 public abstract bool IsInstance {
2609 /// Whether this is a static member.
2611 public abstract bool IsStatic {
2616 /// The type which declares this member.
2618 public abstract Type DeclaringType {
2623 /// The instance expression associated with this member, if it's a
2624 /// non-static member.
2626 public Expression InstanceExpression;
2628 public static void error176 (Location loc, string name)
2630 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2631 "with an instance reference, qualify it with a type name instead", name);
2634 protected bool CheckIntermediateModification ()
2636 if (!InstanceExpression.Type.IsValueType)
2639 if (InstanceExpression is UnboxCast) {
2640 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
2644 if (!(InstanceExpression is IMemoryLocation)) {
2645 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
2646 InstanceExpression.GetSignatureForError ());
2653 // TODO: possible optimalization
2654 // Cache resolved constant result in FieldBuilder <-> expression map
2655 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2656 SimpleName original)
2660 // original == null || original.Resolve (...) ==> left
2663 if (left is TypeExpr) {
2665 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2673 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2676 error176 (loc, GetSignatureForError ());
2680 InstanceExpression = left;
2685 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2690 if (InstanceExpression == EmptyExpression.Null) {
2691 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2695 if (InstanceExpression.Type.IsValueType) {
2696 if (InstanceExpression is IMemoryLocation) {
2697 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2699 LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type);
2700 InstanceExpression.Emit (ec);
2702 t.AddressOf (ec, AddressOp.Store);
2705 InstanceExpression.Emit (ec);
2707 if (prepare_for_load)
2708 ec.ig.Emit (OpCodes.Dup);
2713 /// MethodGroup Expression.
2715 /// This is a fully resolved expression that evaluates to a type
2717 public class MethodGroupExpr : MemberExpr {
2718 public MethodBase [] Methods;
2719 bool has_type_arguments = false;
2720 bool identical_type_name = false;
2723 public MethodGroupExpr (MemberInfo [] mi, Location l)
2725 Methods = new MethodBase [mi.Length];
2726 mi.CopyTo (Methods, 0);
2727 eclass = ExprClass.MethodGroup;
2728 type = TypeManager.object_type;
2732 public MethodGroupExpr (ArrayList list, Location l)
2734 Methods = new MethodBase [list.Count];
2737 list.CopyTo (Methods, 0);
2739 foreach (MemberInfo m in list){
2740 if (!(m is MethodBase)){
2741 Console.WriteLine ("Name " + m.Name);
2742 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2749 eclass = ExprClass.MethodGroup;
2750 type = TypeManager.object_type;
2753 public override Type DeclaringType {
2756 // We assume that the top-level type is in the end
2758 return Methods [Methods.Length - 1].DeclaringType;
2759 //return Methods [0].DeclaringType;
2763 public bool HasTypeArguments {
2765 return has_type_arguments;
2769 has_type_arguments = value;
2773 public bool IdenticalTypeName {
2775 return identical_type_name;
2779 identical_type_name = value;
2783 public bool IsBase {
2792 public override string GetSignatureForError ()
2794 return TypeManager.CSharpSignature (Methods [0]);
2797 public override string Name {
2799 return Methods [0].Name;
2803 public override bool IsInstance {
2805 foreach (MethodBase mb in Methods)
2813 public override bool IsStatic {
2815 foreach (MethodBase mb in Methods)
2823 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2824 SimpleName original)
2826 if (!(left is TypeExpr) &&
2827 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2828 IdenticalTypeName = true;
2830 return base.ResolveMemberAccess (ec, left, loc, original);
2833 override public Expression DoResolve (EmitContext ec)
2836 InstanceExpression = null;
2838 if (InstanceExpression != null) {
2839 InstanceExpression = InstanceExpression.DoResolve (ec);
2840 if (InstanceExpression == null)
2847 public void ReportUsageError ()
2849 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2850 Name + "()' is referenced without parentheses");
2853 override public void Emit (EmitContext ec)
2855 ReportUsageError ();
2858 bool RemoveMethods (bool keep_static)
2860 ArrayList smethods = new ArrayList ();
2862 foreach (MethodBase mb in Methods){
2863 if (mb.IsStatic == keep_static)
2867 if (smethods.Count == 0)
2870 Methods = new MethodBase [smethods.Count];
2871 smethods.CopyTo (Methods, 0);
2877 /// Removes any instance methods from the MethodGroup, returns
2878 /// false if the resulting set is empty.
2880 public bool RemoveInstanceMethods ()
2882 return RemoveMethods (true);
2886 /// Removes any static methods from the MethodGroup, returns
2887 /// false if the resulting set is empty.
2889 public bool RemoveStaticMethods ()
2891 return RemoveMethods (false);
2894 public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
2896 if (args.Resolve (ec) == false)
2899 Type[] atypes = args.Arguments;
2901 int first_count = 0;
2902 MethodInfo first = null;
2904 ArrayList list = new ArrayList ();
2905 foreach (MethodBase mb in Methods) {
2906 MethodInfo mi = mb as MethodInfo;
2907 if ((mi == null) || !mi.HasGenericParameters)
2910 Type[] gen_params = mi.GetGenericArguments ();
2912 if (first == null) {
2914 first_count = gen_params.Length;
2917 if (gen_params.Length != atypes.Length)
2920 list.Add (mi.MakeGenericMethod (atypes));
2923 if (list.Count > 0) {
2924 MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
2925 new_mg.InstanceExpression = InstanceExpression;
2926 new_mg.HasTypeArguments = true;
2932 305, loc, "Using the generic method `{0}' " +
2933 "requires {1} type arguments", Name,
2934 first_count.ToString ());
2937 308, loc, "The non-generic method `{0}' " +
2938 "cannot be used with type arguments", Name);
2945 /// Fully resolved expression that evaluates to a Field
2947 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2948 public readonly FieldInfo FieldInfo;
2949 VariableInfo variable_info;
2951 LocalTemporary temp;
2953 bool in_initializer;
2955 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2958 this.in_initializer = in_initializer;
2961 public FieldExpr (FieldInfo fi, Location l)
2964 eclass = ExprClass.Variable;
2965 type = TypeManager.TypeToCoreType (fi.FieldType);
2969 public override string Name {
2971 return FieldInfo.Name;
2975 public override bool IsInstance {
2977 return !FieldInfo.IsStatic;
2981 public override bool IsStatic {
2983 return FieldInfo.IsStatic;
2987 public override Type DeclaringType {
2989 return FieldInfo.DeclaringType;
2993 public override string GetSignatureForError ()
2995 return TypeManager.GetFullNameSignature (FieldInfo);
2998 public VariableInfo VariableInfo {
3000 return variable_info;
3004 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3005 SimpleName original)
3007 FieldInfo fi = FieldInfo.Mono_GetGenericFieldDefinition ();
3009 Type t = fi.FieldType;
3011 if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
3012 IConstant ic = TypeManager.GetConstant (fi);
3015 ic = new ExternalConstant (fi);
3017 ic = ExternalConstant.CreateDecimal (fi);
3019 return base.ResolveMemberAccess (ec, left, loc, original);
3022 TypeManager.RegisterConstant (fi, ic);
3025 bool left_is_type = left is TypeExpr;
3026 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
3027 Report.SymbolRelatedToPreviousError (FieldInfo);
3028 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
3032 if (ic.ResolveValue ())
3033 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 f.CheckObsoleteness (loc);
3091 // To be sure that type is external because we do not register generated fields
3092 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
3093 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
3095 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
3099 AnonymousContainer am = ec.CurrentAnonymousMethod;
3101 if (!FieldInfo.IsStatic){
3102 if (!am.IsIterator && (ec.TypeContainer is Struct)){
3103 Report.Error (1673, loc,
3104 "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",
3108 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
3109 ec.CaptureField (this);
3113 // If the instance expression is a local variable or parameter.
3114 IVariable var = InstanceExpression as IVariable;
3115 if ((var == null) || (var.VariableInfo == null))
3118 VariableInfo vi = var.VariableInfo;
3119 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
3122 variable_info = vi.GetSubStruct (FieldInfo.Name);
3126 void Report_AssignToReadonly (bool is_instance)
3131 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
3133 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
3135 Report.Error (is_instance ? 191 : 198, loc, msg);
3138 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3140 IVariable var = InstanceExpression as IVariable;
3141 if ((var != null) && (var.VariableInfo != null))
3142 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
3144 Expression e = DoResolve (ec);
3149 if (!FieldInfo.IsStatic && !CheckIntermediateModification ())
3152 FieldBase fb = TypeManager.GetField (FieldInfo);
3156 if (!FieldInfo.IsInitOnly)
3160 // InitOnly fields can only be assigned in constructors
3163 if (ec.IsConstructor){
3164 if (IsStatic && !ec.IsStatic)
3165 Report_AssignToReadonly (false);
3168 if (ec.TypeContainer.CurrentType != null)
3169 ctype = ec.TypeContainer.CurrentType;
3171 ctype = ec.ContainerType;
3173 if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
3177 Report_AssignToReadonly (!IsStatic);
3182 public override void CheckMarshallByRefAccess (Type container)
3184 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
3185 Report.SymbolRelatedToPreviousError (DeclaringType);
3186 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",
3187 GetSignatureForError ());
3191 public bool VerifyFixed ()
3193 IVariable variable = InstanceExpression as IVariable;
3194 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
3195 // We defer the InstanceExpression check after the variable check to avoid a
3196 // separate null check on InstanceExpression.
3197 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
3200 public override int GetHashCode()
3202 return FieldInfo.GetHashCode ();
3205 public override bool Equals (object obj)
3207 FieldExpr fe = obj as FieldExpr;
3211 if (FieldInfo != fe.FieldInfo)
3214 if (InstanceExpression == null || fe.InstanceExpression == null)
3217 return InstanceExpression.Equals (fe.InstanceExpression);
3220 public void Emit (EmitContext ec, bool leave_copy)
3222 ILGenerator ig = ec.ig;
3223 bool is_volatile = false;
3225 FieldInfo the_fi = FieldInfo.Mono_GetGenericFieldDefinition ();
3226 if (the_fi is FieldBuilder){
3227 FieldBase f = TypeManager.GetField (the_fi);
3229 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3232 f.SetMemberIsUsed ();
3236 if (FieldInfo.IsStatic){
3238 ig.Emit (OpCodes.Volatile);
3240 ig.Emit (OpCodes.Ldsfld, FieldInfo);
3243 EmitInstance (ec, false);
3246 ig.Emit (OpCodes.Volatile);
3248 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
3251 ig.Emit (OpCodes.Ldflda, FieldInfo);
3252 ig.Emit (OpCodes.Ldflda, ff.Element);
3255 ig.Emit (OpCodes.Ldfld, FieldInfo);
3260 ec.ig.Emit (OpCodes.Dup);
3261 if (!FieldInfo.IsStatic) {
3262 temp = new LocalTemporary (ec, this.Type);
3268 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3270 FieldAttributes fa = FieldInfo.Attributes;
3271 bool is_static = (fa & FieldAttributes.Static) != 0;
3272 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3273 ILGenerator ig = ec.ig;
3274 prepared = prepare_for_load;
3276 if (is_readonly && !ec.IsConstructor){
3277 Report_AssignToReadonly (!is_static);
3281 EmitInstance (ec, prepare_for_load);
3285 ec.ig.Emit (OpCodes.Dup);
3286 if (!FieldInfo.IsStatic) {
3287 temp = new LocalTemporary (ec, this.Type);
3292 if (FieldInfo is FieldBuilder){
3293 FieldBase f = TypeManager.GetField (FieldInfo);
3295 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3296 ig.Emit (OpCodes.Volatile);
3303 ig.Emit (OpCodes.Stsfld, FieldInfo);
3305 ig.Emit (OpCodes.Stfld, FieldInfo);
3311 public override void Emit (EmitContext ec)
3316 public void AddressOf (EmitContext ec, AddressOp mode)
3318 ILGenerator ig = ec.ig;
3320 if (FieldInfo is FieldBuilder){
3321 FieldBase f = TypeManager.GetField (FieldInfo);
3323 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3324 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3325 f.GetSignatureForError ());
3329 if ((mode & AddressOp.Store) != 0)
3331 if ((mode & AddressOp.Load) != 0)
3332 f.SetMemberIsUsed ();
3337 // Handle initonly fields specially: make a copy and then
3338 // get the address of the copy.
3341 if (FieldInfo.IsInitOnly){
3343 if (ec.IsConstructor){
3344 if (FieldInfo.IsStatic){
3356 local = ig.DeclareLocal (type);
3357 ig.Emit (OpCodes.Stloc, local);
3358 ig.Emit (OpCodes.Ldloca, local);
3363 if (FieldInfo.IsStatic){
3364 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3366 EmitInstance (ec, false);
3367 ig.Emit (OpCodes.Ldflda, FieldInfo);
3373 // A FieldExpr whose address can not be taken
3375 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3376 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3380 public new void AddressOf (EmitContext ec, AddressOp mode)
3382 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3387 /// Expression that evaluates to a Property. The Assign class
3388 /// might set the `Value' expression if we are in an assignment.
3390 /// This is not an LValue because we need to re-write the expression, we
3391 /// can not take data from the stack and store it.
3393 public class PropertyExpr : MemberExpr, IAssignMethod {
3394 public readonly PropertyInfo PropertyInfo;
3397 // This is set externally by the `BaseAccess' class
3400 MethodInfo getter, setter;
3405 LocalTemporary temp;
3408 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3410 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
3413 eclass = ExprClass.PropertyAccess;
3417 type = TypeManager.TypeToCoreType (pi.PropertyType);
3419 ResolveAccessors (ec);
3422 public override string Name {
3424 return PropertyInfo.Name;
3428 public override bool IsInstance {
3434 public override bool IsStatic {
3440 public override Type DeclaringType {
3442 return PropertyInfo.DeclaringType;
3446 public override string GetSignatureForError ()
3448 return TypeManager.GetFullNameSignature (PropertyInfo);
3451 void FindAccessors (Type invocation_type)
3453 BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3454 BindingFlags.Static | BindingFlags.Instance |
3455 BindingFlags.DeclaredOnly;
3457 Type current = PropertyInfo.DeclaringType;
3458 for (; current != null; current = current.BaseType) {
3459 MemberInfo[] group = TypeManager.MemberLookup (
3460 invocation_type, invocation_type, current,
3461 MemberTypes.Property, flags, PropertyInfo.Name, null);
3466 if (group.Length != 1)
3467 // Oooops, can this ever happen ?
3470 PropertyInfo pi = (PropertyInfo) group [0];
3473 getter = pi.GetGetMethod (true);
3476 setter = pi.GetSetMethod (true);
3478 MethodInfo accessor = getter != null ? getter : setter;
3480 if (!accessor.IsVirtual)
3486 // We also perform the permission checking here, as the PropertyInfo does not
3487 // hold the information for the accessibility of its setter/getter
3489 void ResolveAccessors (EmitContext ec)
3491 FindAccessors (ec.ContainerType);
3493 if (getter != null) {
3494 MethodInfo the_getter = getter;
3495 if (the_getter.Mono_IsInflatedMethod)
3496 the_getter = the_getter.GetGenericMethodDefinition ();
3497 IMethodData md = TypeManager.GetMethod (the_getter);
3499 md.SetMemberIsUsed ();
3501 AccessorTable [getter] = PropertyInfo;
3502 is_static = getter.IsStatic;
3505 if (setter != null) {
3506 MethodInfo the_setter = setter;
3507 if (the_setter.Mono_IsInflatedMethod)
3508 the_setter = the_setter.GetGenericMethodDefinition ();
3509 IMethodData md = TypeManager.GetMethod (the_setter);
3511 md.SetMemberIsUsed ();
3513 AccessorTable [setter] = PropertyInfo;
3514 is_static = setter.IsStatic;
3518 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3521 InstanceExpression = null;
3525 if (InstanceExpression == null) {
3526 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3530 InstanceExpression = InstanceExpression.DoResolve (ec);
3531 if (InstanceExpression == null)
3534 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3536 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3537 InstanceExpression.Type != ec.ContainerType &&
3538 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3539 InstanceExpression.Type.IsSubclassOf (PropertyInfo.DeclaringType)) {
3540 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3547 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3549 // TODO: correctly we should compare arguments but it will lead to bigger changes
3550 if (mi is MethodBuilder) {
3551 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3555 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3557 ParameterData iparams = TypeManager.GetParameterData (mi);
3558 sig.Append (getter ? "get_" : "set_");
3560 sig.Append (iparams.GetSignatureForError ());
3562 Report.SymbolRelatedToPreviousError (mi);
3563 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3564 Name, sig.ToString ());
3567 override public Expression DoResolve (EmitContext ec)
3572 if (getter != null){
3573 if (TypeManager.GetArgumentTypes (getter).Length != 0){
3574 Error_PropertyNotFound (getter, true);
3579 if (getter == null){
3581 // The following condition happens if the PropertyExpr was
3582 // created, but is invalid (ie, the property is inaccessible),
3583 // and we did not want to embed the knowledge about this in
3584 // the caller routine. This only avoids double error reporting.
3589 if (InstanceExpression != EmptyExpression.Null) {
3590 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3591 TypeManager.GetFullNameSignature (PropertyInfo));
3596 bool must_do_cs1540_check = false;
3597 if (getter != null &&
3598 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3599 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3600 if (pm != null && pm.HasCustomAccessModifier) {
3601 Report.SymbolRelatedToPreviousError (pm);
3602 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3603 TypeManager.CSharpSignature (getter));
3606 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3610 if (!InstanceResolve (ec, must_do_cs1540_check))
3614 // Only base will allow this invocation to happen.
3616 if (IsBase && getter.IsAbstract) {
3617 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3621 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3631 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3633 if (setter == null){
3635 // The following condition happens if the PropertyExpr was
3636 // created, but is invalid (ie, the property is inaccessible),
3637 // and we did not want to embed the knowledge about this in
3638 // the caller routine. This only avoids double error reporting.
3643 Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)",
3644 TypeManager.GetFullNameSignature (PropertyInfo));
3648 if (TypeManager.GetArgumentTypes (setter).Length != 1){
3649 Error_PropertyNotFound (setter, false);
3653 bool must_do_cs1540_check;
3654 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3655 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3656 if (pm != null && pm.HasCustomAccessModifier) {
3657 Report.SymbolRelatedToPreviousError (pm);
3658 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3659 TypeManager.CSharpSignature (setter));
3662 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3666 if (!InstanceResolve (ec, must_do_cs1540_check))
3670 // Only base will allow this invocation to happen.
3672 if (IsBase && setter.IsAbstract){
3673 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3678 // Check that we are not making changes to a temporary memory location
3680 if (InstanceExpression != null && !CheckIntermediateModification ())
3686 public override void Emit (EmitContext ec)
3691 public void Emit (EmitContext ec, bool leave_copy)
3694 // Special case: length of single dimension array property is turned into ldlen
3696 if ((getter == TypeManager.system_int_array_get_length) ||
3697 (getter == TypeManager.int_array_get_length)){
3698 Type iet = InstanceExpression.Type;
3701 // System.Array.Length can be called, but the Type does not
3702 // support invoking GetArrayRank, so test for that case first
3704 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3706 EmitInstance (ec, false);
3707 ec.ig.Emit (OpCodes.Ldlen);
3708 ec.ig.Emit (OpCodes.Conv_I4);
3713 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3716 ec.ig.Emit (OpCodes.Dup);
3718 temp = new LocalTemporary (ec, this.Type);
3725 // Implements the IAssignMethod interface for assignments
3727 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3729 Expression my_source = source;
3731 prepared = prepare_for_load;
3736 ec.ig.Emit (OpCodes.Dup);
3738 temp = new LocalTemporary (ec, this.Type);
3742 } else if (leave_copy) {
3745 temp = new LocalTemporary (ec, this.Type);
3751 ArrayList args = new ArrayList (1);
3752 args.Add (new Argument (my_source, Argument.AType.Expression));
3754 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3762 /// Fully resolved expression that evaluates to an Event
3764 public class EventExpr : MemberExpr {
3765 public readonly EventInfo EventInfo;
3768 MethodInfo add_accessor, remove_accessor;
3770 public EventExpr (EventInfo ei, Location loc)
3774 eclass = ExprClass.EventAccess;
3776 add_accessor = TypeManager.GetAddMethod (ei);
3777 remove_accessor = TypeManager.GetRemoveMethod (ei);
3779 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3782 if (EventInfo is MyEventBuilder){
3783 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3784 type = eb.EventType;
3787 type = EventInfo.EventHandlerType;
3790 public override string Name {
3792 return EventInfo.Name;
3796 public override bool IsInstance {
3802 public override bool IsStatic {
3808 public override Type DeclaringType {
3810 return EventInfo.DeclaringType;
3814 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3815 SimpleName original)
3818 // If the event is local to this class, we transform ourselves into a FieldExpr
3821 if (EventInfo.DeclaringType == ec.ContainerType ||
3822 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3823 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3826 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc);
3829 Report.Error (-200, loc, "Internal error!!");
3833 InstanceExpression = null;
3835 return ml.ResolveMemberAccess (ec, left, loc, original);
3839 return base.ResolveMemberAccess (ec, left, loc, original);
3843 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3846 InstanceExpression = null;
3850 if (InstanceExpression == null) {
3851 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3855 InstanceExpression = InstanceExpression.DoResolve (ec);
3856 if (InstanceExpression == null)
3860 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3861 // However, in the Event case, we reported a CS0122 instead.
3863 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) {
3864 if ((InstanceExpression.Type != ec.ContainerType) &&
3865 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3866 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3874 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3876 return DoResolve (ec);
3879 public override Expression DoResolve (EmitContext ec)
3881 bool must_do_cs1540_check;
3882 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3883 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3884 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3888 if (!InstanceResolve (ec, must_do_cs1540_check))
3894 public override void Emit (EmitContext ec)
3896 if (InstanceExpression is This)
3897 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3899 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3900 "(except on the defining type)", Name);
3903 public override string GetSignatureForError ()
3905 return TypeManager.CSharpSignature (EventInfo);
3908 public void EmitAddOrRemove (EmitContext ec, Expression source)
3910 BinaryDelegate source_del = (BinaryDelegate) source;
3911 Expression handler = source_del.Right;
3913 Argument arg = new Argument (handler, Argument.AType.Expression);
3914 ArrayList args = new ArrayList ();
3918 if (source_del.IsAddition)
3919 Invocation.EmitCall (
3920 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3922 Invocation.EmitCall (
3923 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3928 public class TemporaryVariable : Expression, IMemoryLocation
3932 public TemporaryVariable (Type type, Location loc)
3936 eclass = ExprClass.Value;
3939 public override Expression DoResolve (EmitContext ec)
3944 TypeExpr te = new TypeExpression (type, loc);
3945 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3946 if (!li.Resolve (ec))
3949 AnonymousContainer am = ec.CurrentAnonymousMethod;
3950 if ((am != null) && am.IsIterator)
3951 ec.CaptureVariable (li);
3956 public override void Emit (EmitContext ec)
3958 ILGenerator ig = ec.ig;
3960 if (li.FieldBuilder != null) {
3961 ig.Emit (OpCodes.Ldarg_0);
3962 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
3964 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
3968 public void EmitLoadAddress (EmitContext ec)
3970 ILGenerator ig = ec.ig;
3972 if (li.FieldBuilder != null) {
3973 ig.Emit (OpCodes.Ldarg_0);
3974 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
3976 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
3980 public void Store (EmitContext ec, Expression right_side)
3982 if (li.FieldBuilder != null)
3983 ec.ig.Emit (OpCodes.Ldarg_0);
3985 right_side.Emit (ec);
3986 if (li.FieldBuilder != null) {
3987 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
3989 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
3993 public void EmitThis (EmitContext ec)
3995 if (li.FieldBuilder != null) {
3996 ec.ig.Emit (OpCodes.Ldarg_0);
4000 public void EmitStore (ILGenerator ig)
4002 if (li.FieldBuilder != null)
4003 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
4005 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
4008 public void AddressOf (EmitContext ec, AddressOp mode)
4010 EmitLoadAddress (ec);