2 // ecore.cs: Core of the Expression representation for the intermediate tree.
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // (C) 2001, 2002, 2003 Ximian, Inc.
12 namespace Mono.CSharp {
14 using System.Collections;
15 using System.Diagnostics;
16 using System.Reflection;
17 using System.Reflection.Emit;
21 /// The ExprClass class contains the is used to pass the
22 /// classification of an expression (value, variable, namespace,
23 /// type, method group, property access, event access, indexer access,
26 public enum ExprClass : byte {
41 /// This is used to tell Resolve in which types of expressions we're
45 public enum ResolveFlags {
46 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
49 // Returns a type expression.
52 // Returns a method group.
55 // Mask of all the expression class flags.
58 // Disable control flow analysis while resolving the expression.
59 // This is used when resolving the instance expression of a field expression.
60 DisableFlowAnalysis = 8,
62 // Set if this is resolving the first part of a MemberAccess.
65 // Disable control flow analysis _of struct_ while resolving the expression.
66 // This is used when resolving the instance expression of a field expression.
67 DisableStructFlowAnalysis = 32,
72 // This is just as a hint to AddressOf of what will be done with the
75 public enum AddressOp {
82 /// This interface is implemented by variables
84 public interface IMemoryLocation {
86 /// The AddressOf method should generate code that loads
87 /// the address of the object and leaves it on the stack.
89 /// The `mode' argument is used to notify the expression
90 /// of whether this will be used to read from the address or
91 /// write to the address.
93 /// This is just a hint that can be used to provide good error
94 /// reporting, and should have no other side effects.
96 void AddressOf (EmitContext ec, AddressOp mode);
100 /// This interface is implemented by variables
102 public interface IVariable {
103 VariableInfo VariableInfo {
111 /// Base class for expressions
113 public abstract class Expression {
114 public ExprClass eclass;
116 protected Location loc;
120 set { type = value; }
123 public virtual Location Location {
128 /// Utility wrapper routine for Error, just to beautify the code
130 public void Error (int error, string s)
133 Report.Error (error, s);
135 Report.Error (error, loc, s);
138 // Not nice but we have broken hierarchy
139 public virtual void CheckMarshallByRefAccess (Type container) {}
141 public virtual bool GetAttributableValue (Type valueType, out object value)
143 Attribute.Error_AttributeArgumentNotValid (loc);
148 public virtual string GetSignatureForError ()
150 return TypeManager.CSharpName (type);
153 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
155 MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
157 must_do_cs1540_check = false; // by default we do not check for this
159 if (ma == MethodAttributes.Public)
163 // If only accessible to the current class or children
165 if (ma == MethodAttributes.Private)
166 return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
167 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
169 if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
170 TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
171 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
174 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
178 // Family and FamANDAssem require that we derive.
179 // FamORAssem requires that we derive if in different assemblies.
180 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
183 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
184 must_do_cs1540_check = true;
190 /// Performs semantic analysis on the Expression
194 /// The Resolve method is invoked to perform the semantic analysis
197 /// The return value is an expression (it can be the
198 /// same expression in some cases) or a new
199 /// expression that better represents this node.
201 /// For example, optimizations of Unary (LiteralInt)
202 /// would return a new LiteralInt with a negated
205 /// If there is an error during semantic analysis,
206 /// then an error should be reported (using Report)
207 /// and a null value should be returned.
209 /// There are two side effects expected from calling
210 /// Resolve(): the the field variable "eclass" should
211 /// be set to any value of the enumeration
212 /// `ExprClass' and the type variable should be set
213 /// to a valid type (this is the type of the
216 public abstract Expression DoResolve (EmitContext ec);
218 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
224 // This is used if the expression should be resolved as a type or namespace name.
225 // the default implementation fails.
227 public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
233 // This is used to resolve the expression as a type, a null
234 // value will be returned if the expression is not a type
237 public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
239 TypeExpr te = ResolveAsBaseTerminal (ec, silent);
243 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
244 if (obsolete_attr != null && !ec.IsInObsoleteScope) {
245 AttributeTester.Report_ObsoleteMessage (obsolete_attr, GetSignatureForError (), Location);
250 public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent)
252 int errors = Report.Errors;
254 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
257 if (!silent && errors == Report.Errors)
258 Report.Error (118, loc, "Expecting a type.");
262 if (fne.eclass != ExprClass.Type) {
263 if (!silent && errors == Report.Errors)
264 fne.Error_UnexpectedKind (null, "type", loc);
268 TypeExpr te = fne as TypeExpr;
270 if (!te.CheckAccessLevel (ec.DeclContainer)) {
271 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
275 // Constrains don't need to be checked for overrides
276 GenericMethod gm = ec.DeclContainer as GenericMethod;
277 if (gm != null && (gm.ModFlags & Modifiers.OVERRIDE) != 0) {
282 ConstructedType ct = te as ConstructedType;
283 if ((ct != null) && !ct.CheckConstraints (ec))
290 public static void ErrorIsInaccesible (Location loc, string name)
292 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
295 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
297 Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"
298 + " the qualifier must be of type `{2}' (or derived from it)",
299 TypeManager.GetFullNameSignature (m),
300 TypeManager.CSharpName (qualifier),
301 TypeManager.CSharpName (container));
305 public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)
307 if (Type.Name == target.Name){
308 Report.ExtraInformation (loc,
310 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
311 Type.Name, Type.Assembly.FullName, target.Assembly.FullName));
316 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
317 GetSignatureForError (), TypeManager.CSharpName (target));
321 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
322 bool b = Convert.ExplicitNumericConversion (e, target) != null;
324 if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {
325 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",
326 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
330 if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {
331 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
332 GetSignatureForError (), TypeManager.CSharpName (target));
336 Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
337 Type == TypeManager.anonymous_method_type ?
338 "anonymous method" : "`" + GetSignatureForError () + "'",
339 TypeManager.CSharpName (target));
342 protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
344 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
345 TypeManager.CSharpName (type), name);
348 ResolveFlags ExprClassToResolveFlags
353 case ExprClass.Namespace:
354 return ResolveFlags.Type;
356 case ExprClass.MethodGroup:
357 return ResolveFlags.MethodGroup;
359 case ExprClass.Value:
360 case ExprClass.Variable:
361 case ExprClass.PropertyAccess:
362 case ExprClass.EventAccess:
363 case ExprClass.IndexerAccess:
364 return ResolveFlags.VariableOrValue;
367 throw new Exception ("Expression " + GetType () +
368 " ExprClass is Invalid after resolve");
374 /// Resolves an expression and performs semantic analysis on it.
378 /// Currently Resolve wraps DoResolve to perform sanity
379 /// checking and assertion checking on what we expect from Resolve.
381 public Expression Resolve (EmitContext ec, ResolveFlags flags)
383 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
384 return ResolveAsTypeStep (ec, false);
386 bool old_do_flow_analysis = ec.DoFlowAnalysis;
387 bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;
388 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
389 ec.DoFlowAnalysis = false;
390 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
391 ec.OmitStructFlowAnalysis = true;
394 if (this is SimpleName) {
395 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
396 e = ((SimpleName) this).DoResolve (ec, intermediate);
401 ec.DoFlowAnalysis = old_do_flow_analysis;
402 ec.OmitStructFlowAnalysis = old_omit_struct_analysis;
407 if ((flags & e.ExprClassToResolveFlags) == 0) {
408 e.Error_UnexpectedKind (flags, loc);
412 if (e.type == null && !(e is Namespace)) {
413 throw new Exception (
414 "Expression " + e.GetType () +
415 " did not set its type after Resolve\n" +
416 "called from: " + this.GetType ());
423 /// Resolves an expression and performs semantic analysis on it.
425 public Expression Resolve (EmitContext ec)
427 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
429 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
430 ((MethodGroupExpr) e).ReportUsageError ();
436 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
438 Expression e = Resolve (ec);
442 Constant c = e as Constant;
446 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
451 /// Resolves an expression for LValue assignment
455 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
456 /// checking and assertion checking on what we expect from Resolve
458 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
460 int errors = Report.Errors;
461 Expression e = DoResolveLValue (ec, right_side);
464 if (errors == Report.Errors)
465 Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
470 if (e.eclass == ExprClass.Invalid)
471 throw new Exception ("Expression " + e +
472 " ExprClass is Invalid after resolve");
474 if (e.eclass == ExprClass.MethodGroup) {
475 ((MethodGroupExpr) e).ReportUsageError ();
479 if ((e.type == null) && !(e is ConstructedType))
480 throw new Exception ("Expression " + e +
481 " did not set its type after Resolve");
488 /// Emits the code for the expression
492 /// The Emit method is invoked to generate the code
493 /// for the expression.
495 public abstract void Emit (EmitContext ec);
497 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
500 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
504 /// Protected constructor. Only derivate types should
505 /// be able to be created
508 protected Expression ()
510 eclass = ExprClass.Invalid;
515 /// Returns a literalized version of a literal FieldInfo
519 /// The possible return values are:
520 /// IntConstant, UIntConstant
521 /// LongLiteral, ULongConstant
522 /// FloatConstant, DoubleConstant
525 /// The value returned is already resolved.
527 public static Constant Constantify (object v, Type t)
529 if (t == TypeManager.int32_type)
530 return new IntConstant ((int) v, Location.Null);
531 else if (t == TypeManager.uint32_type)
532 return new UIntConstant ((uint) v, Location.Null);
533 else if (t == TypeManager.int64_type)
534 return new LongConstant ((long) v, Location.Null);
535 else if (t == TypeManager.uint64_type)
536 return new ULongConstant ((ulong) v, Location.Null);
537 else if (t == TypeManager.float_type)
538 return new FloatConstant ((float) v, Location.Null);
539 else if (t == TypeManager.double_type)
540 return new DoubleConstant ((double) v, Location.Null);
541 else if (t == TypeManager.string_type)
542 return new StringConstant ((string) v, Location.Null);
543 else if (t == TypeManager.short_type)
544 return new ShortConstant ((short)v, Location.Null);
545 else if (t == TypeManager.ushort_type)
546 return new UShortConstant ((ushort)v, Location.Null);
547 else if (t == TypeManager.sbyte_type)
548 return new SByteConstant ((sbyte)v, Location.Null);
549 else if (t == TypeManager.byte_type)
550 return new ByteConstant ((byte)v, Location.Null);
551 else if (t == TypeManager.char_type)
552 return new CharConstant ((char)v, Location.Null);
553 else if (t == TypeManager.bool_type)
554 return new BoolConstant ((bool) v, Location.Null);
555 else if (t == TypeManager.decimal_type)
556 return new DecimalConstant ((decimal) v, Location.Null);
557 else if (TypeManager.IsEnumType (t)){
558 Type real_type = TypeManager.TypeToCoreType (v.GetType ());
560 real_type = System.Enum.GetUnderlyingType (real_type);
562 Constant e = Constantify (v, real_type);
564 return new EnumConstant (e, t);
565 } else if (v == null && !TypeManager.IsValueType (t))
566 return new NullLiteral (Location.Null);
568 throw new Exception ("Unknown type for constant (" + t +
573 /// Returns a fully formed expression after a MemberLookup
576 public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
579 return new EventExpr ((EventInfo) mi, loc);
580 else if (mi is FieldInfo)
581 return new FieldExpr ((FieldInfo) mi, loc);
582 else if (mi is PropertyInfo)
583 return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
584 else if (mi is Type){
585 return new TypeExpression ((System.Type) mi, loc);
591 protected static ArrayList almostMatchedMembers = new ArrayList (4);
594 // FIXME: Probably implement a cache for (t,name,current_access_set)?
596 // This code could use some optimizations, but we need to do some
597 // measurements. For example, we could use a delegate to `flag' when
598 // something can not any longer be a method-group (because it is something
602 // If the return value is an Array, then it is an array of
605 // If the return value is an MemberInfo, it is anything, but a Method
609 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
610 // the arguments here and have MemberLookup return only the methods that
611 // match the argument count/type, unlike we are doing now (we delay this
614 // This is so we can catch correctly attempts to invoke instance methods
615 // from a static body (scan for error 120 in ResolveSimpleName).
618 // FIXME: Potential optimization, have a static ArrayList
621 public static Expression MemberLookup (Type container_type, Type queried_type, string name,
622 MemberTypes mt, BindingFlags bf, Location loc)
624 return MemberLookup (container_type, null, queried_type, name, mt, bf, loc);
628 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
629 // `qualifier_type' or null to lookup members in the current class.
632 public static Expression MemberLookup (Type container_type,
633 Type qualifier_type, Type queried_type,
634 string name, MemberTypes mt,
635 BindingFlags bf, Location loc)
637 almostMatchedMembers.Clear ();
639 MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
640 queried_type, mt, bf, name, almostMatchedMembers);
645 int count = mi.Length;
647 if (mi [0] is MethodBase)
648 return new MethodGroupExpr (mi, loc);
653 return ExprClassFromMemberInfo (container_type, mi [0], loc);
656 public const MemberTypes AllMemberTypes =
657 MemberTypes.Constructor |
661 MemberTypes.NestedType |
662 MemberTypes.Property;
664 public const BindingFlags AllBindingFlags =
665 BindingFlags.Public |
666 BindingFlags.Static |
667 BindingFlags.Instance;
669 public static Expression MemberLookup (Type container_type, Type queried_type,
670 string name, Location loc)
672 return MemberLookup (container_type, null, queried_type, name,
673 AllMemberTypes, AllBindingFlags, loc);
676 public static Expression MemberLookup (Type container_type, Type qualifier_type,
677 Type queried_type, string name, Location loc)
679 return MemberLookup (container_type, qualifier_type, queried_type,
680 name, AllMemberTypes, AllBindingFlags, loc);
683 public static Expression MethodLookup (EmitContext ec, Type queried_type,
684 string name, Location loc)
686 return MemberLookup (ec.ContainerType, null, queried_type, name,
687 MemberTypes.Method, AllBindingFlags, loc);
691 /// This is a wrapper for MemberLookup that is not used to "probe", but
692 /// to find a final definition. If the final definition is not found, we
693 /// look for private members and display a useful debugging message if we
696 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
697 Type queried_type, string name, Location loc)
699 return MemberLookupFinal (ec, qualifier_type, queried_type, name,
700 AllMemberTypes, AllBindingFlags, loc);
703 public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
704 Type queried_type, string name,
705 MemberTypes mt, BindingFlags bf,
710 int errors = Report.Errors;
712 e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
714 if (e == null && errors == Report.Errors)
715 // No errors were reported by MemberLookup, but there was an error.
716 MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
721 public static void MemberLookupFailed (Type container_type, Type qualifier_type,
722 Type queried_type, string name,
723 string class_name, bool complain_if_none_found,
726 if (almostMatchedMembers.Count != 0) {
727 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
728 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
729 for (int j = 0; j < i; ++j) {
730 if (m == almostMatchedMembers [j]) {
738 Type declaring_type = m.DeclaringType;
740 Report.SymbolRelatedToPreviousError (m);
741 if (qualifier_type == null) {
742 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
743 TypeManager.CSharpName (m.DeclaringType),
744 TypeManager.CSharpName (container_type));
746 } else if (qualifier_type != container_type &&
747 TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) {
748 // Although a derived class can access protected members of
749 // its base class it cannot do so through an instance of the
750 // base class (CS1540). If the qualifier_type is a base of the
751 // ec.ContainerType and the lookup succeeds with the latter one,
752 // then we are in this situation.
753 Error_CannotAccessProtected (loc, m, qualifier_type, container_type);
755 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
758 almostMatchedMembers.Clear ();
762 MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
763 AllMemberTypes, AllBindingFlags |
764 BindingFlags.NonPublic, name, null);
766 if (lookup == null) {
767 if (!complain_if_none_found)
770 if (class_name != null)
771 Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
774 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
778 if (TypeManager.MemberLookup (queried_type, null, queried_type,
779 AllMemberTypes, AllBindingFlags |
780 BindingFlags.NonPublic, name, null) == null) {
781 if ((lookup.Length == 1) && (lookup [0] is Type)) {
782 Type t = (Type) lookup [0];
784 Report.Error (305, loc,
785 "Using the generic type `{0}' " +
786 "requires {1} type arguments",
787 TypeManager.CSharpName (t),
788 TypeManager.GetNumberOfTypeArguments (t).ToString ());
793 MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
794 BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
795 if (name == ".ctor" && ml.Count == 0)
797 Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
801 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
805 /// Returns an expression that can be used to invoke operator true
806 /// on the expression if it exists.
808 static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
810 return GetOperatorTrueOrFalse (ec, e, true, loc);
814 /// Returns an expression that can be used to invoke operator false
815 /// on the expression if it exists.
817 static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
819 return GetOperatorTrueOrFalse (ec, e, false, loc);
822 static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
825 Expression operator_group;
827 if (TypeManager.IsNullableType (e.Type))
828 return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
830 operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
831 if (operator_group == null)
834 ArrayList arguments = new ArrayList ();
835 arguments.Add (new Argument (e, Argument.AType.Expression));
836 method = Invocation.OverloadResolve (
837 ec, (MethodGroupExpr) operator_group, arguments, false, loc);
842 return new StaticCallExpr ((MethodInfo) method, arguments, loc);
846 /// Resolves the expression `e' into a boolean expression: either through
847 /// an implicit conversion, or through an `operator true' invocation
849 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
855 if (e.Type == TypeManager.bool_type)
858 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
860 if (converted != null)
864 // If no implicit conversion to bool exists, try using `operator true'
866 converted = Expression.GetOperatorTrue (ec, e, loc);
867 if (converted == null){
868 e.Error_ValueCannotBeConverted (loc, TypeManager.bool_type, false);
874 public virtual string ExprClassName
878 case ExprClass.Invalid:
880 case ExprClass.Value:
882 case ExprClass.Variable:
884 case ExprClass.Namespace:
888 case ExprClass.MethodGroup:
889 return "method group";
890 case ExprClass.PropertyAccess:
891 return "property access";
892 case ExprClass.EventAccess:
893 return "event access";
894 case ExprClass.IndexerAccess:
895 return "indexer access";
896 case ExprClass.Nothing:
899 throw new Exception ("Should not happen");
904 /// Reports that we were expecting `expr' to be of class `expected'
906 public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
908 Error_UnexpectedKind (ds, expected, ExprClassName, loc);
911 public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
913 string name = GetSignatureForError ();
915 name = ds.GetSignatureForError () + '.' + name;
917 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
918 name, was, expected);
921 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
923 string [] valid = new string [4];
926 if ((flags & ResolveFlags.VariableOrValue) != 0) {
927 valid [count++] = "variable";
928 valid [count++] = "value";
931 if ((flags & ResolveFlags.Type) != 0)
932 valid [count++] = "type";
934 if ((flags & ResolveFlags.MethodGroup) != 0)
935 valid [count++] = "method group";
938 valid [count++] = "unknown";
940 StringBuilder sb = new StringBuilder (valid [0]);
941 for (int i = 1; i < count - 1; i++) {
943 sb.Append (valid [i]);
946 sb.Append ("' or `");
947 sb.Append (valid [count - 1]);
950 Report.Error (119, loc,
951 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
954 public static void UnsafeError (Location loc)
956 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
960 // Load the object from the pointer.
962 public static void LoadFromPtr (ILGenerator ig, Type t)
964 if (t == TypeManager.int32_type)
965 ig.Emit (OpCodes.Ldind_I4);
966 else if (t == TypeManager.uint32_type)
967 ig.Emit (OpCodes.Ldind_U4);
968 else if (t == TypeManager.short_type)
969 ig.Emit (OpCodes.Ldind_I2);
970 else if (t == TypeManager.ushort_type)
971 ig.Emit (OpCodes.Ldind_U2);
972 else if (t == TypeManager.char_type)
973 ig.Emit (OpCodes.Ldind_U2);
974 else if (t == TypeManager.byte_type)
975 ig.Emit (OpCodes.Ldind_U1);
976 else if (t == TypeManager.sbyte_type)
977 ig.Emit (OpCodes.Ldind_I1);
978 else if (t == TypeManager.uint64_type)
979 ig.Emit (OpCodes.Ldind_I8);
980 else if (t == TypeManager.int64_type)
981 ig.Emit (OpCodes.Ldind_I8);
982 else if (t == TypeManager.float_type)
983 ig.Emit (OpCodes.Ldind_R4);
984 else if (t == TypeManager.double_type)
985 ig.Emit (OpCodes.Ldind_R8);
986 else if (t == TypeManager.bool_type)
987 ig.Emit (OpCodes.Ldind_I1);
988 else if (t == TypeManager.intptr_type)
989 ig.Emit (OpCodes.Ldind_I);
990 else if (TypeManager.IsEnumType (t)) {
991 if (t == TypeManager.enum_type)
992 ig.Emit (OpCodes.Ldind_Ref);
994 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
995 } else if (t.IsValueType || t.IsGenericParameter)
996 ig.Emit (OpCodes.Ldobj, t);
997 else if (t.IsPointer)
998 ig.Emit (OpCodes.Ldind_I);
1000 ig.Emit (OpCodes.Ldind_Ref);
1004 // The stack contains the pointer and the value of type `type'
1006 public static void StoreFromPtr (ILGenerator ig, Type type)
1008 if (TypeManager.IsEnumType (type))
1009 type = TypeManager.EnumToUnderlying (type);
1010 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
1011 ig.Emit (OpCodes.Stind_I4);
1012 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
1013 ig.Emit (OpCodes.Stind_I8);
1014 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
1015 type == TypeManager.ushort_type)
1016 ig.Emit (OpCodes.Stind_I2);
1017 else if (type == TypeManager.float_type)
1018 ig.Emit (OpCodes.Stind_R4);
1019 else if (type == TypeManager.double_type)
1020 ig.Emit (OpCodes.Stind_R8);
1021 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1022 type == TypeManager.bool_type)
1023 ig.Emit (OpCodes.Stind_I1);
1024 else if (type == TypeManager.intptr_type)
1025 ig.Emit (OpCodes.Stind_I);
1026 else if (type.IsValueType || type.IsGenericParameter)
1027 ig.Emit (OpCodes.Stobj, type);
1029 ig.Emit (OpCodes.Stind_Ref);
1033 // Returns the size of type `t' if known, otherwise, 0
1035 public static int GetTypeSize (Type t)
1037 t = TypeManager.TypeToCoreType (t);
1038 if (t == TypeManager.int32_type ||
1039 t == TypeManager.uint32_type ||
1040 t == TypeManager.float_type)
1042 else if (t == TypeManager.int64_type ||
1043 t == TypeManager.uint64_type ||
1044 t == TypeManager.double_type)
1046 else if (t == TypeManager.byte_type ||
1047 t == TypeManager.sbyte_type ||
1048 t == TypeManager.bool_type)
1050 else if (t == TypeManager.short_type ||
1051 t == TypeManager.char_type ||
1052 t == TypeManager.ushort_type)
1054 else if (t == TypeManager.decimal_type)
1060 public static void Error_NegativeArrayIndex (Location loc)
1062 Report.Error (248, loc, "Cannot create an array with a negative size");
1065 protected void Error_CannotCallAbstractBase (string name)
1067 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1071 // Converts `source' to an int, uint, long or ulong.
1073 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1077 bool old_checked = ec.CheckState;
1078 ec.CheckState = true;
1080 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1081 if (target == null){
1082 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1083 if (target == null){
1084 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1085 if (target == null){
1086 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1088 source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false);
1092 ec.CheckState = old_checked;
1095 // Only positive constants are allowed at compile time
1097 if (target is Constant){
1098 if (target is IntConstant){
1099 if (((IntConstant) target).Value < 0){
1100 Error_NegativeArrayIndex (loc);
1105 if (target is LongConstant){
1106 if (((LongConstant) target).Value < 0){
1107 Error_NegativeArrayIndex (loc);
1120 /// This is just a base class for expressions that can
1121 /// appear on statements (invocations, object creation,
1122 /// assignments, post/pre increment and decrement). The idea
1123 /// being that they would support an extra Emition interface that
1124 /// does not leave a result on the stack.
1126 public abstract class ExpressionStatement : Expression {
1128 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1130 Expression e = Resolve (ec);
1134 ExpressionStatement es = e as ExpressionStatement;
1136 Error (201, "Only assignment, call, increment, decrement and new object " +
1137 "expressions can be used as a statement");
1143 /// Requests the expression to be emitted in a `statement'
1144 /// context. This means that no new value is left on the
1145 /// stack after invoking this method (constrasted with
1146 /// Emit that will always leave a value on the stack).
1148 public abstract void EmitStatement (EmitContext ec);
1152 /// This kind of cast is used to encapsulate the child
1153 /// whose type is child.Type into an expression that is
1154 /// reported to return "return_type". This is used to encapsulate
1155 /// expressions which have compatible types, but need to be dealt
1156 /// at higher levels with.
1158 /// For example, a "byte" expression could be encapsulated in one
1159 /// of these as an "unsigned int". The type for the expression
1160 /// would be "unsigned int".
1163 public class EmptyCast : Expression {
1164 protected readonly Expression child;
1166 public EmptyCast (Expression child, Type return_type)
1168 eclass = child.eclass;
1169 loc = child.Location;
1174 public override Expression DoResolve (EmitContext ec)
1176 // This should never be invoked, we are born in fully
1177 // initialized state.
1182 public override void Emit (EmitContext ec)
1187 public override bool GetAttributableValue (Type valueType, out object value)
1189 return child.GetAttributableValue (valueType, out value);
1194 /// This is a numeric cast to a Decimal
1196 public class CastToDecimal : EmptyCast {
1198 MethodInfo conversion_operator;
1200 public CastToDecimal (Expression child)
1201 : this (child, false)
1205 public CastToDecimal (Expression child, bool find_explicit)
1206 : base (child, TypeManager.decimal_type)
1208 conversion_operator = GetConversionOperator (find_explicit);
1210 if (conversion_operator == null)
1211 throw new InternalErrorException ("Outer conversion routine is out of sync");
1214 // Returns the implicit operator that converts from
1215 // 'child.Type' to System.Decimal.
1216 MethodInfo GetConversionOperator (bool find_explicit)
1218 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1220 MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1221 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1223 foreach (MethodInfo oper in mi) {
1224 ParameterData pd = TypeManager.GetParameterData (oper);
1226 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1232 public override void Emit (EmitContext ec)
1234 ILGenerator ig = ec.ig;
1237 ig.Emit (OpCodes.Call, conversion_operator);
1242 /// This is an explicit numeric cast from a Decimal
1244 public class CastFromDecimal : EmptyCast
1246 static IDictionary operators;
1248 public CastFromDecimal (Expression child, Type return_type)
1249 : base (child, return_type)
1251 if (child.Type != TypeManager.decimal_type)
1252 throw new InternalErrorException (
1253 "The expected type is Decimal, instead it is " + child.Type.FullName);
1256 // Returns the explicit operator that converts from an
1257 // express of type System.Decimal to 'type'.
1258 public Expression Resolve ()
1260 if (operators == null) {
1261 MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1262 TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1263 BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1265 operators = new System.Collections.Specialized.HybridDictionary ();
1266 foreach (MethodInfo oper in all_oper) {
1267 ParameterData pd = TypeManager.GetParameterData (oper);
1268 if (pd.ParameterType (0) == TypeManager.decimal_type)
1269 operators.Add (oper.ReturnType, oper);
1273 return operators.Contains (type) ? this : null;
1276 public override void Emit (EmitContext ec)
1278 ILGenerator ig = ec.ig;
1281 ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1286 // We need to special case this since an empty cast of
1287 // a NullLiteral is still a Constant
1289 public class NullCast : Constant {
1290 public Constant child;
1292 public NullCast (Constant child, Type return_type):
1293 base (Location.Null)
1295 eclass = child.eclass;
1300 override public string AsString ()
1305 public override object GetValue ()
1310 public override Expression DoResolve (EmitContext ec)
1312 // This should never be invoked, we are born in fully
1313 // initialized state.
1318 public override void Emit (EmitContext ec)
1323 public override Constant Increment ()
1325 throw new NotSupportedException ();
1328 public override bool IsDefaultValue {
1334 public override bool IsNegative {
1340 public override Constant Reduce (bool inCheckedContext, Type target_type)
1342 if (type == target_type)
1343 return child.Reduce (inCheckedContext, target_type);
1352 /// This class is used to wrap literals which belong inside Enums
1354 public class EnumConstant : Constant {
1355 public Constant Child;
1357 public EnumConstant (Constant child, Type enum_type):
1358 base (child.Location)
1360 eclass = child.eclass;
1365 public override Expression DoResolve (EmitContext ec)
1367 // This should never be invoked, we are born in fully
1368 // initialized state.
1373 public override void Emit (EmitContext ec)
1378 public override bool GetAttributableValue (Type valueType, out object value)
1380 value = GetTypedValue ();
1384 public override string GetSignatureForError()
1386 return TypeManager.CSharpName (Type);
1389 public override object GetValue ()
1391 return Child.GetValue ();
1394 public override object GetTypedValue ()
1396 // FIXME: runtime is not ready to work with just emited enums
1397 if (!RootContext.StdLib) {
1398 return Child.GetValue ();
1401 return System.Enum.ToObject (type, Child.GetValue ());
1404 public override string AsString ()
1406 return Child.AsString ();
1409 public override DoubleConstant ConvertToDouble ()
1411 return Child.ConvertToDouble ();
1414 public override FloatConstant ConvertToFloat ()
1416 return Child.ConvertToFloat ();
1419 public override ULongConstant ConvertToULong ()
1421 return Child.ConvertToULong ();
1424 public override LongConstant ConvertToLong ()
1426 return Child.ConvertToLong ();
1429 public override UIntConstant ConvertToUInt ()
1431 return Child.ConvertToUInt ();
1434 public override IntConstant ConvertToInt ()
1436 return Child.ConvertToInt ();
1439 public override Constant Increment()
1441 return new EnumConstant (Child.Increment (), type);
1444 public override bool IsDefaultValue {
1446 return Child.IsDefaultValue;
1450 public override bool IsZeroInteger {
1451 get { return Child.IsZeroInteger; }
1454 public override bool IsNegative {
1456 return Child.IsNegative;
1460 public override Constant Reduce(bool inCheckedContext, Type target_type)
1462 if (Child.Type == target_type)
1465 return Child.Reduce (inCheckedContext, target_type);
1468 public override Constant ToType (Type type, Location loc)
1471 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1472 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1475 if (type.UnderlyingSystemType != Child.Type)
1476 Child = Child.ToType (type.UnderlyingSystemType, loc);
1480 if (!Convert.ImplicitStandardConversionExists (this, type)){
1481 Error_ValueCannotBeConverted (loc, type, false);
1485 return Child.ToType (type, loc);
1491 /// This kind of cast is used to encapsulate Value Types in objects.
1493 /// The effect of it is to box the value type emitted by the previous
1496 public class BoxedCast : EmptyCast {
1498 public BoxedCast (Expression expr, Type target_type)
1499 : base (expr, target_type)
1501 eclass = ExprClass.Value;
1504 public override Expression DoResolve (EmitContext ec)
1506 // This should never be invoked, we are born in fully
1507 // initialized state.
1512 public override void Emit (EmitContext ec)
1516 ec.ig.Emit (OpCodes.Box, child.Type);
1520 public class UnboxCast : EmptyCast {
1521 public UnboxCast (Expression expr, Type return_type)
1522 : base (expr, return_type)
1526 public override Expression DoResolve (EmitContext ec)
1528 // This should never be invoked, we are born in fully
1529 // initialized state.
1534 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1536 if (right_side == EmptyExpression.LValueMemberAccess)
1537 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1538 return base.DoResolveLValue (ec, right_side);
1541 public override void Emit (EmitContext ec)
1544 ILGenerator ig = ec.ig;
1547 if (t.IsGenericParameter)
1548 ig.Emit (OpCodes.Unbox_Any, t);
1550 ig.Emit (OpCodes.Unbox, t);
1552 LoadFromPtr (ig, t);
1558 /// This is used to perform explicit numeric conversions.
1560 /// Explicit numeric conversions might trigger exceptions in a checked
1561 /// context, so they should generate the conv.ovf opcodes instead of
1564 public class ConvCast : EmptyCast {
1565 public enum Mode : byte {
1566 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1568 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1569 U2_I1, U2_U1, U2_I2, U2_CH,
1570 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1571 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1572 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1573 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1574 CH_I1, CH_U1, CH_I2,
1575 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1576 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1581 public ConvCast (Expression child, Type return_type, Mode m)
1582 : base (child, return_type)
1587 public override Expression DoResolve (EmitContext ec)
1589 // This should never be invoked, we are born in fully
1590 // initialized state.
1595 public override string ToString ()
1597 return String.Format ("ConvCast ({0}, {1})", mode, child);
1600 public override void Emit (EmitContext ec)
1602 ILGenerator ig = ec.ig;
1608 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1609 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1610 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1611 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1612 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1614 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1615 case Mode.U1_CH: /* nothing */ break;
1617 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1618 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1619 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1620 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1621 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1622 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1624 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1625 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1626 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1627 case Mode.U2_CH: /* nothing */ break;
1629 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1630 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1631 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1632 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1633 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1634 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1635 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1637 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1638 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1639 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1640 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1641 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1642 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1644 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1645 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1646 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1647 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1648 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1649 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1650 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1651 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1653 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1654 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1655 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1656 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1657 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1658 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1659 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1660 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1662 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1663 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1664 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1666 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1667 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1668 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1669 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1670 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1671 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1672 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1673 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1674 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1676 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1677 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1678 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1679 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1680 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1681 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1682 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1683 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1684 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1685 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1689 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1690 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1691 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1692 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1693 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1695 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1696 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1698 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1699 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1700 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1701 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1702 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1703 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1705 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1706 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1707 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1708 case Mode.U2_CH: /* nothing */ break;
1710 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1711 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1712 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1713 case Mode.I4_U4: /* nothing */ break;
1714 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1715 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1716 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1718 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1719 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1720 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1721 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1722 case Mode.U4_I4: /* nothing */ break;
1723 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1725 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1726 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1727 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1728 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1729 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1730 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1731 case Mode.I8_U8: /* nothing */ break;
1732 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1734 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1735 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1736 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1737 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1738 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1739 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1740 case Mode.U8_I8: /* nothing */ break;
1741 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1743 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1744 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1745 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1747 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1748 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1749 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1750 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1751 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1752 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1753 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1754 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1755 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1757 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1758 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1759 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1760 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1761 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1762 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1763 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1764 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1765 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1766 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1772 public class OpcodeCast : EmptyCast {
1776 public OpcodeCast (Expression child, Type return_type, OpCode op)
1777 : base (child, return_type)
1781 second_valid = false;
1784 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1785 : base (child, return_type)
1790 second_valid = true;
1793 public override Expression DoResolve (EmitContext ec)
1795 // This should never be invoked, we are born in fully
1796 // initialized state.
1801 public override void Emit (EmitContext ec)
1812 /// This kind of cast is used to encapsulate a child and cast it
1813 /// to the class requested
1815 public class ClassCast : EmptyCast {
1816 public ClassCast (Expression child, Type return_type)
1817 : base (child, return_type)
1822 public override Expression DoResolve (EmitContext ec)
1824 // This should never be invoked, we are born in fully
1825 // initialized state.
1830 public override void Emit (EmitContext ec)
1834 if (child.Type.IsGenericParameter)
1835 ec.ig.Emit (OpCodes.Box, child.Type);
1837 if (type.IsGenericParameter)
1838 ec.ig.Emit (OpCodes.Unbox_Any, type);
1840 ec.ig.Emit (OpCodes.Castclass, type);
1845 /// SimpleName expressions are formed of a single word and only happen at the beginning
1846 /// of a dotted-name.
1848 public class SimpleName : Expression {
1850 public readonly TypeArguments Arguments;
1853 public SimpleName (string name, Location l)
1859 public SimpleName (string name, TypeArguments args, Location l)
1866 public SimpleName (string name, TypeParameter[] type_params, Location l)
1871 Arguments = new TypeArguments (l);
1872 foreach (TypeParameter type_param in type_params)
1873 Arguments.Add (new TypeParameterExpr (type_param, l));
1876 public static string RemoveGenericArity (string name)
1879 StringBuilder sb = new StringBuilder ();
1880 while (start < name.Length) {
1881 int pos = name.IndexOf ('`', start);
1883 sb.Append (name.Substring (start));
1887 sb.Append (name.Substring (start, pos-start));
1890 while ((pos < name.Length) && Char.IsNumber (name [pos]))
1896 return sb.ToString ();
1899 public SimpleName GetMethodGroup ()
1901 return new SimpleName (RemoveGenericArity (Name), Arguments, loc);
1904 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
1906 if (ec.IsFieldInitializer)
1907 Report.Error (236, l,
1908 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
1911 if (name.LastIndexOf ('.') > 0)
1912 name = name.Substring (name.LastIndexOf ('.') + 1);
1915 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
1920 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
1922 return resolved_to != null && resolved_to.Type != null &&
1923 resolved_to.Type.Name == Name &&
1924 (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null);
1927 public override Expression DoResolve (EmitContext ec)
1929 return SimpleNameResolve (ec, null, false);
1932 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1934 return SimpleNameResolve (ec, right_side, false);
1938 public Expression DoResolve (EmitContext ec, bool intermediate)
1940 return SimpleNameResolve (ec, null, intermediate);
1943 private bool IsNestedChild (Type t, Type parent)
1948 while (parent != null) {
1949 parent = TypeManager.DropGenericTypeArguments (parent);
1950 if (TypeManager.IsNestedChildOf (t, parent))
1953 parent = parent.BaseType;
1959 FullNamedExpression ResolveNested (IResolveContext ec, Type t)
1961 if (!t.IsGenericTypeDefinition)
1964 DeclSpace ds = ec.DeclContainer;
1965 while (ds != null) {
1966 if (IsNestedChild (t, ds.TypeBuilder))
1975 Type[] gen_params = t.GetGenericArguments ();
1977 int arg_count = Arguments != null ? Arguments.Count : 0;
1979 for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
1980 if (arg_count + ds.CountTypeParameters == gen_params.Length) {
1981 TypeArguments new_args = new TypeArguments (loc);
1982 foreach (TypeParameter param in ds.TypeParameters)
1983 new_args.Add (new TypeParameterExpr (param, loc));
1985 if (Arguments != null)
1986 new_args.Add (Arguments);
1988 return new ConstructedType (t, new_args, loc);
1995 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
1997 FullNamedExpression fne = ec.DeclContainer.LookupGeneric (Name, loc);
1999 return fne.ResolveAsTypeStep (ec, silent);
2001 int errors = Report.Errors;
2002 fne = ec.DeclContainer.LookupType (Name, loc, /*ignore_cs0104=*/ false);
2005 if (fne.Type == null)
2008 FullNamedExpression nested = ResolveNested (ec, fne.Type);
2010 return nested.ResolveAsTypeStep (ec, false);
2012 if (Arguments != null) {
2013 ConstructedType ct = new ConstructedType (fne, Arguments, loc);
2014 return ct.ResolveAsTypeStep (ec, false);
2020 if (silent || errors != Report.Errors)
2023 MemberCore mc = ec.DeclContainer.GetDefinition (Name);
2025 Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
2029 string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
2030 string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
2031 foreach (Assembly a in RootNamespace.Global.Assemblies) {
2032 Type type = a.GetType (fullname);
2034 Report.SymbolRelatedToPreviousError (type);
2035 Expression.ErrorIsInaccesible (loc, fullname);
2040 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
2044 // TODO: I am still not convinced about this. If someone else will need it
2045 // implement this as virtual property in MemberCore hierarchy
2046 string GetMemberType (MemberCore mc)
2048 if (mc is PropertyBase)
2052 if (mc is FieldBase)
2054 if (mc is MethodCore)
2056 if (mc is EnumMember)
2062 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2068 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2072 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2079 /// 7.5.2: Simple Names.
2081 /// Local Variables and Parameters are handled at
2082 /// parse time, so they never occur as SimpleNames.
2084 /// The `intermediate' flag is used by MemberAccess only
2085 /// and it is used to inform us that it is ok for us to
2086 /// avoid the static check, because MemberAccess might end
2087 /// up resolving the Name as a Type name and the access as
2088 /// a static type access.
2090 /// ie: Type Type; .... { Type.GetType (""); }
2092 /// Type is both an instance variable and a Type; Type.GetType
2093 /// is the static method not an instance method of type.
2095 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2097 Expression e = null;
2100 // Stage 1: Performed by the parser (binding to locals or parameters).
2102 Block current_block = ec.CurrentBlock;
2103 if (current_block != null){
2104 LocalInfo vi = current_block.GetLocalInfo (Name);
2106 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2107 if (right_side != null) {
2108 return var.ResolveLValue (ec, right_side, loc);
2110 ResolveFlags rf = ResolveFlags.VariableOrValue;
2112 rf |= ResolveFlags.DisableFlowAnalysis;
2113 return var.Resolve (ec, rf);
2117 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
2119 if (right_side != null)
2120 return pref.ResolveLValue (ec, right_side, loc);
2122 return pref.Resolve (ec);
2127 // Stage 2: Lookup members
2130 DeclSpace lookup_ds = ec.DeclContainer;
2131 Type almost_matched_type = null;
2132 ArrayList almost_matched = null;
2134 if (lookup_ds.TypeBuilder == null)
2137 e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
2141 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2142 almost_matched_type = lookup_ds.TypeBuilder;
2143 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2146 lookup_ds =lookup_ds.Parent;
2147 } while (lookup_ds != null);
2149 if (e == null && ec.ContainerType != null)
2150 e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
2153 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2154 almost_matched_type = ec.ContainerType;
2155 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2157 e = ResolveAsTypeStep (ec, true);
2161 if (almost_matched != null)
2162 almostMatchedMembers = almost_matched;
2163 if (almost_matched_type == null)
2164 almost_matched_type = ec.ContainerType;
2165 MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
2172 if (e is MemberExpr) {
2173 MemberExpr me = (MemberExpr) e;
2176 if (me.IsInstance) {
2177 if (ec.IsStatic || ec.IsFieldInitializer) {
2179 // Note that an MemberExpr can be both IsInstance and IsStatic.
2180 // An unresolved MethodGroupExpr can contain both kinds of methods
2181 // and each predicate is true if the MethodGroupExpr contains
2182 // at least one of that kind of method.
2186 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2187 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2188 return EmptyExpression.Null;
2192 // Pass the buck to MemberAccess and Invocation.
2194 left = EmptyExpression.Null;
2196 left = ec.GetThis (loc);
2199 left = new TypeExpression (ec.ContainerType, loc);
2202 e = me.ResolveMemberAccess (ec, left, loc, null);
2206 me = e as MemberExpr;
2210 if (Arguments != null) {
2211 MethodGroupExpr mg = me as MethodGroupExpr;
2215 return mg.ResolveGeneric (ec, Arguments);
2219 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2220 me.InstanceExpression.Type != me.DeclaringType &&
2221 !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2222 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2223 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2224 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2228 return (right_side != null)
2229 ? me.DoResolveLValue (ec, right_side)
2230 : me.DoResolve (ec);
2236 public override void Emit (EmitContext ec)
2239 // If this is ever reached, then we failed to
2240 // find the name as a namespace
2243 Error (103, "The name `" + Name +
2244 "' does not exist in the class `" +
2245 ec.DeclContainer.Name + "'");
2248 public override string ToString ()
2253 public override string GetSignatureForError ()
2260 /// Represents a namespace or a type. The name of the class was inspired by
2261 /// section 10.8.1 (Fully Qualified Names).
2263 public abstract class FullNamedExpression : Expression {
2264 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2269 public abstract string FullName {
2275 /// Expression that evaluates to a type
2277 public abstract class TypeExpr : FullNamedExpression {
2278 override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2280 TypeExpr t = DoResolveAsTypeStep (ec);
2284 eclass = ExprClass.Type;
2288 override public Expression DoResolve (EmitContext ec)
2290 return ResolveAsTypeTerminal (ec, false);
2293 override public void Emit (EmitContext ec)
2295 throw new Exception ("Should never be called");
2298 public virtual bool CheckAccessLevel (DeclSpace ds)
2300 return ds.CheckAccessLevel (Type);
2303 public virtual bool AsAccessible (DeclSpace ds, int flags)
2305 return ds.AsAccessible (Type, flags);
2308 public virtual bool IsClass {
2309 get { return Type.IsClass; }
2312 public virtual bool IsValueType {
2313 get { return Type.IsValueType; }
2316 public virtual bool IsInterface {
2317 get { return Type.IsInterface; }
2320 public virtual bool IsSealed {
2321 get { return Type.IsSealed; }
2324 public virtual bool CanInheritFrom ()
2326 if (Type == TypeManager.enum_type ||
2327 (Type == TypeManager.value_type && RootContext.StdLib) ||
2328 Type == TypeManager.multicast_delegate_type ||
2329 Type == TypeManager.delegate_type ||
2330 Type == TypeManager.array_type)
2336 protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
2338 public abstract string Name {
2342 public override bool Equals (object obj)
2344 TypeExpr tobj = obj as TypeExpr;
2348 return Type == tobj.Type;
2351 public override int GetHashCode ()
2353 return Type.GetHashCode ();
2356 public override string ToString ()
2363 /// Fully resolved Expression that already evaluated to a type
2365 public class TypeExpression : TypeExpr {
2366 public TypeExpression (Type t, Location l)
2369 eclass = ExprClass.Type;
2373 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2378 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2383 public override string Name {
2384 get { return Type.ToString (); }
2387 public override string FullName {
2388 get { return Type.FullName; }
2393 /// Used to create types from a fully qualified name. These are just used
2394 /// by the parser to setup the core types. A TypeLookupExpression is always
2395 /// classified as a type.
2397 public sealed class TypeLookupExpression : TypeExpr {
2398 readonly string name;
2400 public TypeLookupExpression (string name)
2403 eclass = ExprClass.Type;
2406 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2408 // It's null for corlib compilation only
2410 return DoResolveAsTypeStep (ec);
2415 static readonly char [] dot_array = { '.' };
2416 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2418 // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
2420 string lookup_name = name;
2421 int pos = name.IndexOf ('.');
2423 rest = name.Substring (pos + 1);
2424 lookup_name = name.Substring (0, pos);
2427 FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
2429 if (resolved != null && rest != null) {
2430 // Now handle the rest of the the name.
2431 string [] elements = rest.Split (dot_array);
2433 int count = elements.Length;
2435 while (i < count && resolved != null && resolved is Namespace) {
2436 Namespace ns = resolved as Namespace;
2437 element = elements [i++];
2438 lookup_name += "." + element;
2439 resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
2442 if (resolved != null && resolved is TypeExpr) {
2443 Type t = ((TypeExpr) resolved).Type;
2445 if (!ec.DeclContainer.CheckAccessLevel (t)) {
2447 lookup_name = t.FullName;
2454 t = TypeManager.GetNestedType (t, elements [i++]);
2459 if (resolved == null) {
2460 NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
2464 if (!(resolved is TypeExpr)) {
2465 resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
2469 type = resolved.Type;
2473 public override string Name {
2474 get { return name; }
2477 public override string FullName {
2478 get { return name; }
2483 /// Represents an "unbound generic type", ie. typeof (Foo<>).
2486 public class UnboundTypeExpression : TypeExpr
2490 public UnboundTypeExpression (MemberName name, Location l)
2496 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2499 if (name.Left != null) {
2500 Expression lexpr = name.Left.GetTypeExpression ();
2501 expr = new MemberAccess (lexpr, name.Basename);
2503 expr = new SimpleName (name.Basename, loc);
2506 FullNamedExpression fne = expr.ResolveAsTypeStep (ec, false);
2511 return new TypeExpression (type, loc);
2514 public override string Name {
2515 get { return name.FullName; }
2518 public override string FullName {
2519 get { return name.FullName; }
2523 public class TypeAliasExpression : TypeExpr {
2524 FullNamedExpression alias;
2529 public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
2535 eclass = ExprClass.Type;
2537 name = alias.FullName + "<" + args.ToString () + ">";
2539 name = alias.FullName;
2542 public override string Name {
2543 get { return alias.FullName; }
2546 public override string FullName {
2547 get { return name; }
2550 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2552 texpr = alias.ResolveAsTypeTerminal (ec, false);
2556 Type type = texpr.Type;
2557 int num_args = TypeManager.GetNumberOfTypeArguments (type);
2560 if (num_args == 0) {
2561 Report.Error (308, loc,
2562 "The non-generic type `{0}' cannot " +
2563 "be used with type arguments.",
2564 TypeManager.CSharpName (type));
2568 ConstructedType ctype = new ConstructedType (type, args, loc);
2569 return ctype.ResolveAsTypeTerminal (ec, false);
2570 } else if (num_args > 0) {
2571 Report.Error (305, loc,
2572 "Using the generic type `{0}' " +
2573 "requires {1} type arguments",
2574 TypeManager.CSharpName (type), num_args.ToString ());
2581 public override bool CheckAccessLevel (DeclSpace ds)
2583 return texpr.CheckAccessLevel (ds);
2586 public override bool AsAccessible (DeclSpace ds, int flags)
2588 return texpr.AsAccessible (ds, flags);
2591 public override bool IsClass {
2592 get { return texpr.IsClass; }
2595 public override bool IsValueType {
2596 get { return texpr.IsValueType; }
2599 public override bool IsInterface {
2600 get { return texpr.IsInterface; }
2603 public override bool IsSealed {
2604 get { return texpr.IsSealed; }
2609 /// This class denotes an expression which evaluates to a member
2610 /// of a struct or a class.
2612 public abstract class MemberExpr : Expression
2615 /// The name of this member.
2617 public abstract string Name {
2622 /// Whether this is an instance member.
2624 public abstract bool IsInstance {
2629 /// Whether this is a static member.
2631 public abstract bool IsStatic {
2636 /// The type which declares this member.
2638 public abstract Type DeclaringType {
2643 /// The instance expression associated with this member, if it's a
2644 /// non-static member.
2646 public Expression InstanceExpression;
2648 public static void error176 (Location loc, string name)
2650 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2651 "with an instance reference, qualify it with a type name instead", name);
2654 // TODO: possible optimalization
2655 // Cache resolved constant result in FieldBuilder <-> expression map
2656 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2657 SimpleName original)
2661 // original == null || original.Resolve (...) ==> left
2664 if (left is TypeExpr) {
2666 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2674 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2677 error176 (loc, GetSignatureForError ());
2681 InstanceExpression = left;
2686 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2691 if (InstanceExpression == EmptyExpression.Null) {
2692 SimpleName.Error_ObjectRefRequired (ec, loc, Name);
2696 if (InstanceExpression.Type.IsValueType) {
2697 if (InstanceExpression is IMemoryLocation) {
2698 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2700 LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
2701 InstanceExpression.Emit (ec);
2703 t.AddressOf (ec, AddressOp.Store);
2706 InstanceExpression.Emit (ec);
2708 if (prepare_for_load)
2709 ec.ig.Emit (OpCodes.Dup);
2714 /// MethodGroup Expression.
2716 /// This is a fully resolved expression that evaluates to a type
2718 public class MethodGroupExpr : MemberExpr {
2719 public MethodBase [] Methods;
2720 bool has_type_arguments = false;
2721 bool identical_type_name = false;
2724 public MethodGroupExpr (MemberInfo [] mi, Location l)
2726 Methods = new MethodBase [mi.Length];
2727 mi.CopyTo (Methods, 0);
2728 eclass = ExprClass.MethodGroup;
2729 type = TypeManager.object_type;
2733 public MethodGroupExpr (ArrayList list, Location l)
2735 Methods = new MethodBase [list.Count];
2738 list.CopyTo (Methods, 0);
2740 foreach (MemberInfo m in list){
2741 if (!(m is MethodBase)){
2742 Console.WriteLine ("Name " + m.Name);
2743 Console.WriteLine ("Found a: " + m.GetType ().FullName);
2750 eclass = ExprClass.MethodGroup;
2751 type = TypeManager.object_type;
2754 public override Type DeclaringType {
2757 // We assume that the top-level type is in the end
2759 return Methods [Methods.Length - 1].DeclaringType;
2760 //return Methods [0].DeclaringType;
2764 public bool HasTypeArguments {
2766 return has_type_arguments;
2770 has_type_arguments = value;
2774 public bool IdenticalTypeName {
2776 return identical_type_name;
2780 identical_type_name = value;
2784 public bool IsBase {
2793 public override string GetSignatureForError ()
2795 return TypeManager.CSharpSignature (Methods [0]);
2798 public override string Name {
2800 return Methods [0].Name;
2804 public override bool IsInstance {
2806 foreach (MethodBase mb in Methods)
2814 public override bool IsStatic {
2816 foreach (MethodBase mb in Methods)
2824 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2825 SimpleName original)
2827 if (!(left is TypeExpr) &&
2828 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2829 IdenticalTypeName = true;
2831 return base.ResolveMemberAccess (ec, left, loc, original);
2834 override public Expression DoResolve (EmitContext ec)
2837 InstanceExpression = null;
2839 if (InstanceExpression != null) {
2840 InstanceExpression = InstanceExpression.DoResolve (ec);
2841 if (InstanceExpression == null)
2848 public void ReportUsageError ()
2850 Report.Error (654, loc, "Method `" + DeclaringType + "." +
2851 Name + "()' is referenced without parentheses");
2854 override public void Emit (EmitContext ec)
2856 ReportUsageError ();
2859 bool RemoveMethods (bool keep_static)
2861 ArrayList smethods = new ArrayList ();
2863 foreach (MethodBase mb in Methods){
2864 if (mb.IsStatic == keep_static)
2868 if (smethods.Count == 0)
2871 Methods = new MethodBase [smethods.Count];
2872 smethods.CopyTo (Methods, 0);
2878 /// Removes any instance methods from the MethodGroup, returns
2879 /// false if the resulting set is empty.
2881 public bool RemoveInstanceMethods ()
2883 return RemoveMethods (true);
2887 /// Removes any static methods from the MethodGroup, returns
2888 /// false if the resulting set is empty.
2890 public bool RemoveStaticMethods ()
2892 return RemoveMethods (false);
2895 public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
2897 if (args.Resolve (ec) == false)
2900 Type[] atypes = args.Arguments;
2902 int first_count = 0;
2903 MethodInfo first = null;
2905 ArrayList list = new ArrayList ();
2906 foreach (MethodBase mb in Methods) {
2907 MethodInfo mi = mb as MethodInfo;
2908 if ((mi == null) || !mi.IsGenericMethod)
2911 Type[] gen_params = mi.GetGenericArguments ();
2913 if (first == null) {
2915 first_count = gen_params.Length;
2918 if (gen_params.Length != atypes.Length)
2921 list.Add (mi.MakeGenericMethod (atypes));
2924 if (list.Count > 0) {
2925 MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
2926 new_mg.InstanceExpression = InstanceExpression;
2927 new_mg.HasTypeArguments = true;
2928 new_mg.IsBase = IsBase;
2934 305, loc, "Using the generic method `{0}' " +
2935 "requires {1} type arguments", Name,
2936 first_count.ToString ());
2939 308, loc, "The non-generic method `{0}' " +
2940 "cannot be used with type arguments", Name);
2947 /// Fully resolved expression that evaluates to a Field
2949 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
2950 public readonly FieldInfo FieldInfo;
2951 VariableInfo variable_info;
2953 LocalTemporary temp;
2955 bool in_initializer;
2957 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
2960 this.in_initializer = in_initializer;
2963 public FieldExpr (FieldInfo fi, Location l)
2966 eclass = ExprClass.Variable;
2967 type = TypeManager.TypeToCoreType (fi.FieldType);
2971 public override string Name {
2973 return FieldInfo.Name;
2977 public override bool IsInstance {
2979 return !FieldInfo.IsStatic;
2983 public override bool IsStatic {
2985 return FieldInfo.IsStatic;
2989 public override Type DeclaringType {
2991 return FieldInfo.DeclaringType;
2995 public override string GetSignatureForError ()
2997 return TypeManager.GetFullNameSignature (FieldInfo);
3000 public VariableInfo VariableInfo {
3002 return variable_info;
3006 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3007 SimpleName original)
3009 FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
3011 Type t = fi.FieldType;
3013 if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
3014 IConstant ic = TypeManager.GetConstant (fi);
3017 ic = new ExternalConstant (fi);
3019 ic = ExternalConstant.CreateDecimal (fi);
3021 return base.ResolveMemberAccess (ec, left, loc, original);
3024 TypeManager.RegisterConstant (fi, ic);
3027 bool left_is_type = left is TypeExpr;
3028 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
3029 Report.SymbolRelatedToPreviousError (FieldInfo);
3030 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
3034 if (ic.ResolveValue ()) {
3035 if (!ec.IsInObsoleteScope)
3036 ic.CheckObsoleteness (loc);
3042 if (t.IsPointer && !ec.InUnsafe) {
3047 return base.ResolveMemberAccess (ec, left, loc, original);
3050 override public Expression DoResolve (EmitContext ec)
3052 return DoResolve (ec, false);
3055 Expression DoResolve (EmitContext ec, bool lvalue_instance)
3057 if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) {
3058 if (FieldInfo.FieldType is TypeBuilder) {
3059 if (FieldInfo.IsStatic)
3060 Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
3061 GetSignatureForError ());
3063 Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)",
3064 TypeManager.CSharpName (DeclaringType), Name);
3066 if (FieldInfo.IsStatic)
3067 Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
3070 Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
3076 if (!FieldInfo.IsStatic){
3077 if (InstanceExpression == null){
3079 // This can happen when referencing an instance field using
3080 // a fully qualified type expression: TypeName.InstanceField = xxx
3082 SimpleName.Error_ObjectRefRequired (ec, loc, FieldInfo.Name);
3086 // Resolve the field's instance expression while flow analysis is turned
3087 // off: when accessing a field "a.b", we must check whether the field
3088 // "a.b" is initialized, not whether the whole struct "a" is initialized.
3090 if (lvalue_instance) {
3091 bool old_do_flow_analysis = ec.DoFlowAnalysis;
3092 ec.DoFlowAnalysis = false;
3093 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3094 ec.DoFlowAnalysis = old_do_flow_analysis;
3096 ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
3097 InstanceExpression = InstanceExpression.Resolve (ec, rf);
3100 if (InstanceExpression == null)
3104 if (!in_initializer && !ec.IsFieldInitializer) {
3105 ObsoleteAttribute oa;
3106 FieldBase f = TypeManager.GetField (FieldInfo);
3108 if (!ec.IsInObsoleteScope)
3109 f.CheckObsoleteness (loc);
3111 // To be sure that type is external because we do not register generated fields
3112 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
3113 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
3115 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
3119 AnonymousContainer am = ec.CurrentAnonymousMethod;
3121 if (!FieldInfo.IsStatic){
3122 if (!am.IsIterator && (ec.TypeContainer is Struct)){
3123 Report.Error (1673, loc,
3124 "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",
3128 if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This))
3129 ec.CaptureField (this);
3133 // If the instance expression is a local variable or parameter.
3134 IVariable var = InstanceExpression as IVariable;
3135 if ((var == null) || (var.VariableInfo == null))
3138 VariableInfo vi = var.VariableInfo;
3139 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
3142 variable_info = vi.GetSubStruct (FieldInfo.Name);
3146 void Report_AssignToReadonly (Expression right_side)
3150 bool need_error_sig = false;
3151 if (right_side == EmptyExpression.LValueMemberAccess) {
3154 msg = "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)";
3157 msg = "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)";
3159 need_error_sig = true;
3160 } else if (IsStatic) {
3162 msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)";
3165 msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)";
3169 Report.Error (code, loc, msg, GetSignatureForError ());
3171 Report.Error (code, loc, msg);
3174 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3176 IVariable var = InstanceExpression as IVariable;
3177 if ((var != null) && (var.VariableInfo != null))
3178 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
3180 bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
3182 Expression e = DoResolve (ec, lvalue_instance);
3187 FieldBase fb = TypeManager.GetField (FieldInfo);
3191 if (!FieldInfo.IsInitOnly)
3195 // InitOnly fields can only be assigned in constructors or initializers
3198 if (ec.IsFieldInitializer)
3201 if (ec.IsConstructor){
3202 if (IsStatic && !ec.IsStatic)
3203 Report_AssignToReadonly (right_side);
3206 if (ec.TypeContainer.CurrentType != null)
3207 ctype = ec.TypeContainer.CurrentType;
3209 ctype = ec.ContainerType;
3211 if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
3215 Report_AssignToReadonly (right_side);
3220 public override void CheckMarshallByRefAccess (Type container)
3222 if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
3223 Report.SymbolRelatedToPreviousError (DeclaringType);
3224 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",
3225 GetSignatureForError ());
3229 public bool VerifyFixed ()
3231 IVariable variable = InstanceExpression as IVariable;
3232 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
3233 // We defer the InstanceExpression check after the variable check to avoid a
3234 // separate null check on InstanceExpression.
3235 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
3238 public override int GetHashCode()
3240 return FieldInfo.GetHashCode ();
3243 public override bool Equals (object obj)
3245 FieldExpr fe = obj as FieldExpr;
3249 if (FieldInfo != fe.FieldInfo)
3252 if (InstanceExpression == null || fe.InstanceExpression == null)
3255 return InstanceExpression.Equals (fe.InstanceExpression);
3258 public void Emit (EmitContext ec, bool leave_copy)
3260 ILGenerator ig = ec.ig;
3261 bool is_volatile = false;
3263 FieldBase f = TypeManager.GetField (FieldInfo);
3265 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3268 f.SetMemberIsUsed ();
3271 if (FieldInfo.IsStatic){
3273 ig.Emit (OpCodes.Volatile);
3275 ig.Emit (OpCodes.Ldsfld, FieldInfo);
3278 EmitInstance (ec, false);
3281 ig.Emit (OpCodes.Volatile);
3283 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
3286 ig.Emit (OpCodes.Ldflda, FieldInfo);
3287 ig.Emit (OpCodes.Ldflda, ff.Element);
3290 ig.Emit (OpCodes.Ldfld, FieldInfo);
3295 ec.ig.Emit (OpCodes.Dup);
3296 if (!FieldInfo.IsStatic) {
3297 temp = new LocalTemporary (this.Type);
3303 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3305 FieldAttributes fa = FieldInfo.Attributes;
3306 bool is_static = (fa & FieldAttributes.Static) != 0;
3307 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
3308 ILGenerator ig = ec.ig;
3309 prepared = prepare_for_load;
3311 if (is_readonly && !ec.IsConstructor){
3312 Report_AssignToReadonly (source);
3316 EmitInstance (ec, prepare_for_load);
3320 ec.ig.Emit (OpCodes.Dup);
3321 if (!FieldInfo.IsStatic) {
3322 temp = new LocalTemporary (this.Type);
3327 if (FieldInfo is FieldBuilder){
3328 FieldBase f = TypeManager.GetField (FieldInfo);
3330 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
3331 ig.Emit (OpCodes.Volatile);
3338 ig.Emit (OpCodes.Stsfld, FieldInfo);
3340 ig.Emit (OpCodes.Stfld, FieldInfo);
3346 public override void Emit (EmitContext ec)
3351 public void AddressOf (EmitContext ec, AddressOp mode)
3353 ILGenerator ig = ec.ig;
3355 if (FieldInfo is FieldBuilder){
3356 FieldBase f = TypeManager.GetField (FieldInfo);
3358 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
3359 Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
3360 f.GetSignatureForError ());
3364 if ((mode & AddressOp.Store) != 0)
3366 if ((mode & AddressOp.Load) != 0)
3367 f.SetMemberIsUsed ();
3372 // Handle initonly fields specially: make a copy and then
3373 // get the address of the copy.
3376 if (FieldInfo.IsInitOnly){
3378 if (ec.IsConstructor){
3379 if (FieldInfo.IsStatic){
3391 local = ig.DeclareLocal (type);
3392 ig.Emit (OpCodes.Stloc, local);
3393 ig.Emit (OpCodes.Ldloca, local);
3398 if (FieldInfo.IsStatic){
3399 ig.Emit (OpCodes.Ldsflda, FieldInfo);
3402 EmitInstance (ec, false);
3403 ig.Emit (OpCodes.Ldflda, FieldInfo);
3409 // A FieldExpr whose address can not be taken
3411 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
3412 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
3416 public new void AddressOf (EmitContext ec, AddressOp mode)
3418 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
3423 /// Expression that evaluates to a Property. The Assign class
3424 /// might set the `Value' expression if we are in an assignment.
3426 /// This is not an LValue because we need to re-write the expression, we
3427 /// can not take data from the stack and store it.
3429 public class PropertyExpr : MemberExpr, IAssignMethod {
3430 public readonly PropertyInfo PropertyInfo;
3433 // This is set externally by the `BaseAccess' class
3436 MethodInfo getter, setter;
3441 LocalTemporary temp;
3444 internal static PtrHashtable AccessorTable = new PtrHashtable ();
3446 public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
3449 eclass = ExprClass.PropertyAccess;
3453 type = TypeManager.TypeToCoreType (pi.PropertyType);
3455 ResolveAccessors (containerType);
3458 public override string Name {
3460 return PropertyInfo.Name;
3464 public override bool IsInstance {
3470 public override bool IsStatic {
3476 public override Type DeclaringType {
3478 return PropertyInfo.DeclaringType;
3482 public override string GetSignatureForError ()
3484 return TypeManager.GetFullNameSignature (PropertyInfo);
3487 void FindAccessors (Type invocation_type)
3489 const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
3490 BindingFlags.Static | BindingFlags.Instance |
3491 BindingFlags.DeclaredOnly;
3493 Type current = PropertyInfo.DeclaringType;
3494 for (; current != null; current = current.BaseType) {
3495 MemberInfo[] group = TypeManager.MemberLookup (
3496 invocation_type, invocation_type, current,
3497 MemberTypes.Property, flags, PropertyInfo.Name, null);
3502 if (group.Length != 1)
3503 // Oooops, can this ever happen ?
3506 PropertyInfo pi = (PropertyInfo) group [0];
3509 getter = pi.GetGetMethod (true);
3512 setter = pi.GetSetMethod (true);
3514 MethodInfo accessor = getter != null ? getter : setter;
3516 if (!accessor.IsVirtual)
3522 // We also perform the permission checking here, as the PropertyInfo does not
3523 // hold the information for the accessibility of its setter/getter
3525 // TODO: can use TypeManager.GetProperty to boost performance
3526 void ResolveAccessors (Type containerType)
3528 FindAccessors (containerType);
3530 if (getter != null) {
3531 MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
3532 IMethodData md = TypeManager.GetMethod (the_getter);
3534 md.SetMemberIsUsed ();
3536 AccessorTable [getter] = PropertyInfo;
3537 is_static = getter.IsStatic;
3540 if (setter != null) {
3541 MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter);
3542 IMethodData md = TypeManager.GetMethod (the_setter);
3544 md.SetMemberIsUsed ();
3546 AccessorTable [setter] = PropertyInfo;
3547 is_static = setter.IsStatic;
3551 bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
3554 InstanceExpression = null;
3558 if (InstanceExpression == null) {
3559 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
3563 if (lvalue_instance)
3564 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
3566 InstanceExpression = InstanceExpression.DoResolve (ec);
3567 if (InstanceExpression == null)
3570 InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
3572 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3573 InstanceExpression.Type != ec.ContainerType &&
3574 ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) &&
3575 !InstanceExpression.Type.IsSubclassOf (ec.ContainerType)) {
3576 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
3583 void Error_PropertyNotFound (MethodInfo mi, bool getter)
3585 // TODO: correctly we should compare arguments but it will lead to bigger changes
3586 if (mi is MethodBuilder) {
3587 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
3591 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
3593 ParameterData iparams = TypeManager.GetParameterData (mi);
3594 sig.Append (getter ? "get_" : "set_");
3596 sig.Append (iparams.GetSignatureForError ());
3598 Report.SymbolRelatedToPreviousError (mi);
3599 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
3600 Name, sig.ToString ());
3603 override public Expression DoResolve (EmitContext ec)
3608 if (getter != null){
3609 if (TypeManager.GetParameterData (getter).Count != 0){
3610 Error_PropertyNotFound (getter, true);
3615 if (getter == null){
3617 // The following condition happens if the PropertyExpr was
3618 // created, but is invalid (ie, the property is inaccessible),
3619 // and we did not want to embed the knowledge about this in
3620 // the caller routine. This only avoids double error reporting.
3625 if (InstanceExpression != EmptyExpression.Null) {
3626 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
3627 TypeManager.GetFullNameSignature (PropertyInfo));
3632 bool must_do_cs1540_check = false;
3633 if (getter != null &&
3634 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
3635 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
3636 if (pm != null && pm.HasCustomAccessModifier) {
3637 Report.SymbolRelatedToPreviousError (pm);
3638 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
3639 TypeManager.CSharpSignature (getter));
3642 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
3646 if (!InstanceResolve (ec, false, must_do_cs1540_check))
3650 // Only base will allow this invocation to happen.
3652 if (IsBase && getter.IsAbstract) {
3653 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3657 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
3667 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3669 if (right_side == EmptyExpression.OutAccess) {
3670 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
3671 GetSignatureForError ());
3675 if (right_side == EmptyExpression.LValueMemberAccess) {
3676 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
3677 GetSignatureForError ());
3681 if (setter == null){
3683 // The following condition happens if the PropertyExpr was
3684 // created, but is invalid (ie, the property is inaccessible),
3685 // and we did not want to embed the knowledge about this in
3686 // the caller routine. This only avoids double error reporting.
3690 Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
3691 GetSignatureForError ());
3695 if (TypeManager.GetParameterData (setter).Count != 1){
3696 Error_PropertyNotFound (setter, false);
3700 bool must_do_cs1540_check;
3701 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
3702 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
3703 if (pm != null && pm.HasCustomAccessModifier) {
3704 Report.SymbolRelatedToPreviousError (pm);
3705 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
3706 TypeManager.CSharpSignature (setter));
3709 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
3713 if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
3717 // Only base will allow this invocation to happen.
3719 if (IsBase && setter.IsAbstract){
3720 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
3727 public override void Emit (EmitContext ec)
3732 public void Emit (EmitContext ec, bool leave_copy)
3735 // Special case: length of single dimension array property is turned into ldlen
3737 if ((getter == TypeManager.system_int_array_get_length) ||
3738 (getter == TypeManager.int_array_get_length)){
3739 Type iet = InstanceExpression.Type;
3742 // System.Array.Length can be called, but the Type does not
3743 // support invoking GetArrayRank, so test for that case first
3745 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
3747 EmitInstance (ec, false);
3748 ec.ig.Emit (OpCodes.Ldlen);
3749 ec.ig.Emit (OpCodes.Conv_I4);
3754 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
3757 ec.ig.Emit (OpCodes.Dup);
3759 temp = new LocalTemporary (this.Type);
3766 // Implements the IAssignMethod interface for assignments
3768 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
3770 Expression my_source = source;
3772 prepared = prepare_for_load;
3777 ec.ig.Emit (OpCodes.Dup);
3779 temp = new LocalTemporary (this.Type);
3783 } else if (leave_copy) {
3786 temp = new LocalTemporary (this.Type);
3792 ArrayList args = new ArrayList (1);
3793 args.Add (new Argument (my_source, Argument.AType.Expression));
3795 Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
3803 /// Fully resolved expression that evaluates to an Event
3805 public class EventExpr : MemberExpr {
3806 public readonly EventInfo EventInfo;
3809 MethodInfo add_accessor, remove_accessor;
3811 public EventExpr (EventInfo ei, Location loc)
3815 eclass = ExprClass.EventAccess;
3817 add_accessor = TypeManager.GetAddMethod (ei);
3818 remove_accessor = TypeManager.GetRemoveMethod (ei);
3820 if (add_accessor.IsStatic || remove_accessor.IsStatic)
3823 if (EventInfo is MyEventBuilder){
3824 MyEventBuilder eb = (MyEventBuilder) EventInfo;
3825 type = eb.EventType;
3828 type = EventInfo.EventHandlerType;
3831 public override string Name {
3833 return EventInfo.Name;
3837 public override bool IsInstance {
3843 public override bool IsStatic {
3849 public override Type DeclaringType {
3851 return EventInfo.DeclaringType;
3855 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3856 SimpleName original)
3859 // If the event is local to this class, we transform ourselves into a FieldExpr
3862 if (EventInfo.DeclaringType == ec.ContainerType ||
3863 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
3864 MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo);
3867 MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc);
3870 Report.Error (-200, loc, "Internal error!!");
3874 InstanceExpression = null;
3876 return ml.ResolveMemberAccess (ec, left, loc, original);
3880 return base.ResolveMemberAccess (ec, left, loc, original);
3884 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
3887 InstanceExpression = null;
3891 if (InstanceExpression == null) {
3892 SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name);
3896 InstanceExpression = InstanceExpression.DoResolve (ec);
3897 if (InstanceExpression == null)
3901 // This is using the same mechanism as the CS1540 check in PropertyExpr.
3902 // However, in the Event case, we reported a CS0122 instead.
3904 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
3905 InstanceExpression.Type != ec.ContainerType &&
3906 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
3907 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3914 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3916 return DoResolve (ec);
3919 public override Expression DoResolve (EmitContext ec)
3921 bool must_do_cs1540_check;
3922 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
3923 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
3924 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
3928 if (!InstanceResolve (ec, must_do_cs1540_check))
3934 public override void Emit (EmitContext ec)
3936 if (InstanceExpression is This)
3937 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
3939 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
3940 "(except on the defining type)", Name);
3943 public override string GetSignatureForError ()
3945 return TypeManager.CSharpSignature (EventInfo);
3948 public void EmitAddOrRemove (EmitContext ec, Expression source)
3950 BinaryDelegate source_del = (BinaryDelegate) source;
3951 Expression handler = source_del.Right;
3953 Argument arg = new Argument (handler, Argument.AType.Expression);
3954 ArrayList args = new ArrayList ();
3958 if (source_del.IsAddition)
3959 Invocation.EmitCall (
3960 ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
3962 Invocation.EmitCall (
3963 ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
3968 public class TemporaryVariable : Expression, IMemoryLocation
3972 public TemporaryVariable (Type type, Location loc)
3976 eclass = ExprClass.Value;
3979 public override Expression DoResolve (EmitContext ec)
3984 TypeExpr te = new TypeExpression (type, loc);
3985 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
3986 if (!li.Resolve (ec))
3989 AnonymousContainer am = ec.CurrentAnonymousMethod;
3990 if ((am != null) && am.IsIterator)
3991 ec.CaptureVariable (li);
3996 public override void Emit (EmitContext ec)
3998 ILGenerator ig = ec.ig;
4000 if (li.FieldBuilder != null) {
4001 ig.Emit (OpCodes.Ldarg_0);
4002 ig.Emit (OpCodes.Ldfld, li.FieldBuilder);
4004 ig.Emit (OpCodes.Ldloc, li.LocalBuilder);
4008 public void EmitLoadAddress (EmitContext ec)
4010 ILGenerator ig = ec.ig;
4012 if (li.FieldBuilder != null) {
4013 ig.Emit (OpCodes.Ldarg_0);
4014 ig.Emit (OpCodes.Ldflda, li.FieldBuilder);
4016 ig.Emit (OpCodes.Ldloca, li.LocalBuilder);
4020 public void Store (EmitContext ec, Expression right_side)
4022 if (li.FieldBuilder != null)
4023 ec.ig.Emit (OpCodes.Ldarg_0);
4025 right_side.Emit (ec);
4026 if (li.FieldBuilder != null) {
4027 ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder);
4029 ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder);
4033 public void EmitThis (EmitContext ec)
4035 if (li.FieldBuilder != null) {
4036 ec.ig.Emit (OpCodes.Ldarg_0);
4040 public void EmitStore (ILGenerator ig)
4042 if (li.FieldBuilder != null)
4043 ig.Emit (OpCodes.Stfld, li.FieldBuilder);
4045 ig.Emit (OpCodes.Stloc, li.LocalBuilder);
4048 public void AddressOf (EmitContext ec, AddressOp mode)
4050 EmitLoadAddress (ec);