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)
132 Report.Error (error, loc, s);
135 // Not nice but we have broken hierarchy.
136 public virtual void CheckMarshalByRefAccess ()
140 public virtual bool GetAttributableValue (Type valueType, out object value)
142 Attribute.Error_AttributeArgumentNotValid (loc);
147 public virtual string GetSignatureForError ()
149 return TypeManager.CSharpName (type);
152 public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)
154 MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;
156 must_do_cs1540_check = false; // by default we do not check for this
158 if (ma == MethodAttributes.Public)
162 // If only accessible to the current class or children
164 if (ma == MethodAttributes.Private)
165 return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) ||
166 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
168 if (mi.DeclaringType.Assembly == invocation_type.Assembly ||
169 TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) {
170 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)
173 if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)
177 // Family and FamANDAssem require that we derive.
178 // FamORAssem requires that we derive if in different assemblies.
179 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
182 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
183 must_do_cs1540_check = true;
189 /// Performs semantic analysis on the Expression
193 /// The Resolve method is invoked to perform the semantic analysis
196 /// The return value is an expression (it can be the
197 /// same expression in some cases) or a new
198 /// expression that better represents this node.
200 /// For example, optimizations of Unary (LiteralInt)
201 /// would return a new LiteralInt with a negated
204 /// If there is an error during semantic analysis,
205 /// then an error should be reported (using Report)
206 /// and a null value should be returned.
208 /// There are two side effects expected from calling
209 /// Resolve(): the the field variable "eclass" should
210 /// be set to any value of the enumeration
211 /// `ExprClass' and the type variable should be set
212 /// to a valid type (this is the type of the
215 public abstract Expression DoResolve (EmitContext ec);
217 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
223 // This is used if the expression should be resolved as a type or namespace name.
224 // the default implementation fails.
226 public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
232 // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
233 // same name exists or as a keyword when no type was found
235 public virtual TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent)
237 return ResolveAsTypeTerminal (rc, silent);
241 // This is used to resolve the expression as a type, a null
242 // value will be returned if the expression is not a type
245 public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
247 TypeExpr te = ResolveAsBaseTerminal (ec, silent);
251 if (!silent) { // && !(te is TypeParameterExpr)) {
252 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
253 if (obsolete_attr != null && !ec.IsInObsoleteScope) {
254 AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location);
258 // Constrains don't need to be checked for overrides
259 GenericMethod gm = ec.GenericDeclContainer as GenericMethod;
260 if (gm != null && (gm.ModFlags & Modifiers.OVERRIDE) != 0) {
265 ConstructedType ct = te as ConstructedType;
266 if ((ct != null) && !ct.CheckConstraints (ec))
272 public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent)
274 int errors = Report.Errors;
276 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
281 if (fne.eclass != ExprClass.Type) {
282 if (!silent && errors == Report.Errors)
283 fne.Error_UnexpectedKind (null, "type", loc);
287 TypeExpr te = fne as TypeExpr;
289 if (!te.CheckAccessLevel (ec.DeclContainer)) {
290 Report.SymbolRelatedToPreviousError (te.Type);
291 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));
299 public static void ErrorIsInaccesible (Location loc, string name)
301 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
304 protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)
306 Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'."
307 + " The qualifier must be of type `{2}' or derived from it",
308 TypeManager.GetFullNameSignature (m),
309 TypeManager.CSharpName (qualifier),
310 TypeManager.CSharpName (container));
314 public static void Error_InvalidExpressionStatement (Location loc)
316 Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " +
317 "expressions can be used as a statement");
320 public void Error_InvalidExpressionStatement ()
322 Error_InvalidExpressionStatement (loc);
325 protected void Error_CannotAssign (string to, string roContext)
327 Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'",
331 public static void Error_VoidInvalidInTheContext (Location loc)
333 Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
336 public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
338 if (Type.FullName == target.FullName){
339 Report.ExtraInformation (loc,
341 "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",
342 Type.FullName, Type.Assembly.FullName, target.Assembly.FullName));
347 Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
348 TypeManager.CSharpName (type), TypeManager.CSharpName (target));
352 Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;
353 bool b = Convert.ExplicitNumericConversion (e, target) != null;
356 Convert.ExplicitReferenceConversionExists (Type, target) ||
357 Convert.ExplicitUnsafe (e, target) != null ||
358 (ec != null && Convert.UserDefinedConversion (ec, this, target, Location.Null, true) != null))
360 Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " +
361 "An explicit conversion exists (are you missing a cast?)",
362 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
366 if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) {
367 Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
368 ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target));
372 Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
373 TypeManager.CSharpName (type),
374 TypeManager.CSharpName (target));
377 protected void Error_VariableIsUsedBeforeItIsDeclared (string name)
379 Report.Error (841, loc, "The variable `{0}' cannot be used before it is declared",
383 public static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
385 Report.SymbolRelatedToPreviousError (type);
386 Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
387 TypeManager.CSharpName (type), name);
390 protected static void Error_ValueAssignment (Location loc)
392 Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
395 ResolveFlags ExprClassToResolveFlags
400 case ExprClass.Namespace:
401 return ResolveFlags.Type;
403 case ExprClass.MethodGroup:
404 return ResolveFlags.MethodGroup;
406 case ExprClass.Value:
407 case ExprClass.Variable:
408 case ExprClass.PropertyAccess:
409 case ExprClass.EventAccess:
410 case ExprClass.IndexerAccess:
411 return ResolveFlags.VariableOrValue;
414 throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve");
420 /// Resolves an expression and performs semantic analysis on it.
424 /// Currently Resolve wraps DoResolve to perform sanity
425 /// checking and assertion checking on what we expect from Resolve.
427 public Expression Resolve (EmitContext ec, ResolveFlags flags)
429 if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type)
430 return ResolveAsTypeStep (ec, false);
432 bool do_flow_analysis = ec.DoFlowAnalysis;
433 bool omit_struct_analysis = ec.OmitStructFlowAnalysis;
434 if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
435 do_flow_analysis = false;
436 if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)
437 omit_struct_analysis = true;
440 using (ec.WithFlowAnalysis (do_flow_analysis, omit_struct_analysis)) {
441 if (this is SimpleName) {
442 bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;
443 e = ((SimpleName) this).DoResolve (ec, intermediate);
452 if ((flags & e.ExprClassToResolveFlags) == 0) {
453 e.Error_UnexpectedKind (flags, loc);
457 if (e.type == null && !(e is Namespace)) {
458 throw new Exception (
459 "Expression " + e.GetType () +
460 " did not set its type after Resolve\n" +
461 "called from: " + this.GetType ());
468 /// Resolves an expression and performs semantic analysis on it.
470 public Expression Resolve (EmitContext ec)
472 Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
474 if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {
475 ((MethodGroupExpr) e).ReportUsageError ();
481 public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)
483 Expression e = Resolve (ec);
487 Constant c = e as Constant;
491 Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());
496 /// Resolves an expression for LValue assignment
500 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
501 /// checking and assertion checking on what we expect from Resolve
503 public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)
505 int errors = Report.Errors;
506 bool out_access = right_side == EmptyExpression.OutAccess;
508 Expression e = DoResolveLValue (ec, right_side);
510 if (e != null && out_access && !(e is IMemoryLocation)) {
511 // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
512 // Enabling this 'throw' will "only" result in deleting useless code elsewhere,
514 //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
515 // e.GetType () + " " + e.GetSignatureForError ());
520 if (errors == Report.Errors) {
522 Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
524 Error_ValueAssignment (loc);
529 if (e.eclass == ExprClass.Invalid)
530 throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
532 if (e.eclass == ExprClass.MethodGroup) {
533 ((MethodGroupExpr) e).ReportUsageError ();
537 if ((e.type == null) && !(e is ConstructedType))
538 throw new Exception ("Expression " + e + " did not set its type after Resolve");
544 /// Emits the code for the expression
548 /// The Emit method is invoked to generate the code
549 /// for the expression.
551 public abstract void Emit (EmitContext ec);
553 public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue)
556 ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
560 /// Protected constructor. Only derivate types should
561 /// be able to be created
564 protected Expression ()
566 eclass = ExprClass.Invalid;
571 /// Returns a fully formed expression after a MemberLookup
574 public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc)
577 return new EventExpr ((EventInfo) mi, loc);
578 else if (mi is FieldInfo)
579 return new FieldExpr ((FieldInfo) mi, loc);
580 else if (mi is PropertyInfo)
581 return new PropertyExpr (containerType, (PropertyInfo) mi, loc);
582 else if (mi is Type){
583 return new TypeExpression ((System.Type) mi, loc);
589 protected static ArrayList almostMatchedMembers = new ArrayList (4);
592 // FIXME: Probably implement a cache for (t,name,current_access_set)?
594 // This code could use some optimizations, but we need to do some
595 // measurements. For example, we could use a delegate to `flag' when
596 // something can not any longer be a method-group (because it is something
600 // If the return value is an Array, then it is an array of
603 // If the return value is an MemberInfo, it is anything, but a Method
607 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
608 // the arguments here and have MemberLookup return only the methods that
609 // match the argument count/type, unlike we are doing now (we delay this
612 // This is so we can catch correctly attempts to invoke instance methods
613 // from a static body (scan for error 120 in ResolveSimpleName).
616 // FIXME: Potential optimization, have a static ArrayList
619 public static Expression MemberLookup (Type container_type, Type queried_type, string name,
620 MemberTypes mt, BindingFlags bf, Location loc)
622 return MemberLookup (container_type, null, queried_type, name, mt, bf, loc);
626 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
627 // `qualifier_type' or null to lookup members in the current class.
630 public static Expression MemberLookup (Type container_type,
631 Type qualifier_type, Type queried_type,
632 string name, MemberTypes mt,
633 BindingFlags bf, Location loc)
635 almostMatchedMembers.Clear ();
637 MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type,
638 queried_type, mt, bf, name, almostMatchedMembers);
644 bool is_interface = qualifier_type != null && qualifier_type.IsInterface;
645 ArrayList methods = new ArrayList (2);
646 ArrayList non_methods = null;
648 foreach (MemberInfo m in mi) {
649 if (m is MethodBase) {
654 if (non_methods == null) {
655 non_methods = new ArrayList (2);
660 foreach (MemberInfo n_m in non_methods) {
661 if (m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (m.DeclaringType, n_m.DeclaringType))
664 Report.SymbolRelatedToPreviousError (m);
665 Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
666 TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (n_m));
671 if (methods.Count == 0)
672 return ExprClassFromMemberInfo (container_type, (MemberInfo)non_methods [0], loc);
674 if (non_methods != null) {
675 MethodBase method = (MethodBase) methods [0];
676 MemberInfo non_method = (MemberInfo) non_methods [0];
677 if (method.DeclaringType == non_method.DeclaringType) {
678 // Cannot happen with C# code, but is valid in IL
679 Report.SymbolRelatedToPreviousError (method);
680 Report.SymbolRelatedToPreviousError (non_method);
681 Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
682 TypeManager.GetFullNameSignature (non_method),
683 TypeManager.CSharpSignature (method));
688 Report.SymbolRelatedToPreviousError (method);
689 Report.SymbolRelatedToPreviousError (non_method);
690 Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
691 TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method));
695 return new MethodGroupExpr (methods, queried_type, loc);
698 if (mi [0] is MethodBase)
699 return new MethodGroupExpr (mi, queried_type, loc);
701 return ExprClassFromMemberInfo (container_type, mi [0], loc);
704 public const MemberTypes AllMemberTypes =
705 MemberTypes.Constructor |
709 MemberTypes.NestedType |
710 MemberTypes.Property;
712 public const BindingFlags AllBindingFlags =
713 BindingFlags.Public |
714 BindingFlags.Static |
715 BindingFlags.Instance;
717 public static Expression MemberLookup (Type container_type, Type queried_type,
718 string name, Location loc)
720 return MemberLookup (container_type, null, queried_type, name,
721 AllMemberTypes, AllBindingFlags, loc);
724 public static Expression MemberLookup (Type container_type, Type qualifier_type,
725 Type queried_type, string name, Location loc)
727 return MemberLookup (container_type, qualifier_type, queried_type,
728 name, AllMemberTypes, AllBindingFlags, loc);
731 public static MethodGroupExpr MethodLookup (Type container_type, Type queried_type,
732 string name, Location loc)
734 return (MethodGroupExpr)MemberLookup (container_type, null, queried_type, name,
735 MemberTypes.Method, AllBindingFlags, loc);
739 /// This is a wrapper for MemberLookup that is not used to "probe", but
740 /// to find a final definition. If the final definition is not found, we
741 /// look for private members and display a useful debugging message if we
744 protected Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
745 Type queried_type, string name,
746 MemberTypes mt, BindingFlags bf,
751 int errors = Report.Errors;
753 e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
755 if (e != null || errors != Report.Errors)
758 // No errors were reported by MemberLookup, but there was an error.
759 return Error_MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type,
763 protected virtual Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
764 Type queried_type, string name, string class_name,
765 MemberTypes mt, BindingFlags bf)
767 if (almostMatchedMembers.Count != 0) {
768 for (int i = 0; i < almostMatchedMembers.Count; ++i) {
769 MemberInfo m = (MemberInfo) almostMatchedMembers [i];
770 for (int j = 0; j < i; ++j) {
771 if (m == almostMatchedMembers [j]) {
779 Type declaring_type = m.DeclaringType;
781 Report.SymbolRelatedToPreviousError (m);
782 if (qualifier_type == null) {
783 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
784 TypeManager.CSharpName (m.DeclaringType),
785 TypeManager.CSharpName (container_type));
787 } else if (qualifier_type != container_type &&
788 TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) {
789 // Although a derived class can access protected members of
790 // its base class it cannot do so through an instance of the
791 // base class (CS1540). If the qualifier_type is a base of the
792 // ec.ContainerType and the lookup succeeds with the latter one,
793 // then we are in this situation.
794 Error_CannotAccessProtected (loc, m, qualifier_type, container_type);
796 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m));
799 almostMatchedMembers.Clear ();
803 MemberInfo[] lookup = null;
804 if (queried_type == null) {
805 class_name = "global::";
807 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
808 mt, (bf & ~BindingFlags.Public) | BindingFlags.NonPublic,
811 if (lookup != null) {
812 Report.SymbolRelatedToPreviousError (lookup [0]);
813 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
814 return Error_MemberLookupFailed (lookup);
817 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
818 AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic,
822 if (lookup == null) {
823 if (class_name != null) {
824 Report.Error (103, loc, "The name `{0}' does not exist in the current context",
827 Error_TypeDoesNotContainDefinition (loc, queried_type, name);
832 if (TypeManager.MemberLookup (queried_type, null, queried_type,
833 AllMemberTypes, AllBindingFlags |
834 BindingFlags.NonPublic, name, null) == null) {
835 if ((lookup.Length == 1) && (lookup [0] is Type)) {
836 Type t = (Type) lookup [0];
838 Report.Error (305, loc,
839 "Using the generic type `{0}' " +
840 "requires {1} type arguments",
841 TypeManager.CSharpName (t),
842 TypeManager.GetNumberOfTypeArguments (t).ToString ());
847 return Error_MemberLookupFailed (lookup);
850 protected virtual Expression Error_MemberLookupFailed (MemberInfo[] members)
852 for (int i = 0; i < members.Length; ++i) {
853 if (!(members [i] is MethodBase))
857 // By default propagate the closest candidates upwards
858 return new MethodGroupExpr (members, type, loc);
862 /// Returns an expression that can be used to invoke operator true
863 /// on the expression if it exists.
865 static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
867 return GetOperatorTrueOrFalse (ec, e, true, loc);
871 /// Returns an expression that can be used to invoke operator false
872 /// on the expression if it exists.
874 static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
876 return GetOperatorTrueOrFalse (ec, e, false, loc);
879 static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
881 MethodGroupExpr operator_group;
884 if (TypeManager.IsNullableType (e.Type))
885 return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
888 operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
889 if (operator_group == null)
892 ArrayList arguments = new ArrayList (1);
893 arguments.Add (new Argument (e, Argument.AType.Expression));
894 operator_group = operator_group.OverloadResolve (
895 ec, arguments, false, loc);
897 if (operator_group == null)
900 return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc);
904 /// Resolves the expression `e' into a boolean expression: either through
905 /// an implicit conversion, or through an `operator true' invocation
907 public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc)
913 if (e.Type == TypeManager.bool_type)
916 Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null);
918 if (converted != null)
922 // If no implicit conversion to bool exists, try using `operator true'
924 converted = Expression.GetOperatorTrue (ec, e, loc);
925 if (converted == null){
926 e.Error_ValueCannotBeConverted (ec, loc, TypeManager.bool_type, false);
932 public virtual string ExprClassName
936 case ExprClass.Invalid:
938 case ExprClass.Value:
940 case ExprClass.Variable:
942 case ExprClass.Namespace:
946 case ExprClass.MethodGroup:
947 return "method group";
948 case ExprClass.PropertyAccess:
949 return "property access";
950 case ExprClass.EventAccess:
951 return "event access";
952 case ExprClass.IndexerAccess:
953 return "indexer access";
954 case ExprClass.Nothing:
957 throw new Exception ("Should not happen");
962 /// Reports that we were expecting `expr' to be of class `expected'
964 public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc)
966 Error_UnexpectedKind (ds, expected, ExprClassName, loc);
969 public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc)
971 string name = GetSignatureForError ();
973 name = ds.GetSignatureForError () + '.' + name;
975 Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
976 name, was, expected);
979 public void Error_UnexpectedKind (ResolveFlags flags, Location loc)
981 string [] valid = new string [4];
984 if ((flags & ResolveFlags.VariableOrValue) != 0) {
985 valid [count++] = "variable";
986 valid [count++] = "value";
989 if ((flags & ResolveFlags.Type) != 0)
990 valid [count++] = "type";
992 if ((flags & ResolveFlags.MethodGroup) != 0)
993 valid [count++] = "method group";
996 valid [count++] = "unknown";
998 StringBuilder sb = new StringBuilder (valid [0]);
999 for (int i = 1; i < count - 1; i++) {
1001 sb.Append (valid [i]);
1004 sb.Append ("' or `");
1005 sb.Append (valid [count - 1]);
1008 Report.Error (119, loc,
1009 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
1012 public static void UnsafeError (Location loc)
1014 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
1018 // Load the object from the pointer.
1020 public static void LoadFromPtr (ILGenerator ig, Type t)
1022 if (t == TypeManager.int32_type)
1023 ig.Emit (OpCodes.Ldind_I4);
1024 else if (t == TypeManager.uint32_type)
1025 ig.Emit (OpCodes.Ldind_U4);
1026 else if (t == TypeManager.short_type)
1027 ig.Emit (OpCodes.Ldind_I2);
1028 else if (t == TypeManager.ushort_type)
1029 ig.Emit (OpCodes.Ldind_U2);
1030 else if (t == TypeManager.char_type)
1031 ig.Emit (OpCodes.Ldind_U2);
1032 else if (t == TypeManager.byte_type)
1033 ig.Emit (OpCodes.Ldind_U1);
1034 else if (t == TypeManager.sbyte_type)
1035 ig.Emit (OpCodes.Ldind_I1);
1036 else if (t == TypeManager.uint64_type)
1037 ig.Emit (OpCodes.Ldind_I8);
1038 else if (t == TypeManager.int64_type)
1039 ig.Emit (OpCodes.Ldind_I8);
1040 else if (t == TypeManager.float_type)
1041 ig.Emit (OpCodes.Ldind_R4);
1042 else if (t == TypeManager.double_type)
1043 ig.Emit (OpCodes.Ldind_R8);
1044 else if (t == TypeManager.bool_type)
1045 ig.Emit (OpCodes.Ldind_I1);
1046 else if (t == TypeManager.intptr_type)
1047 ig.Emit (OpCodes.Ldind_I);
1048 else if (TypeManager.IsEnumType (t)) {
1049 if (t == TypeManager.enum_type)
1050 ig.Emit (OpCodes.Ldind_Ref);
1052 LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
1053 } else if (t.IsValueType || TypeManager.IsGenericParameter (t))
1054 ig.Emit (OpCodes.Ldobj, t);
1055 else if (t.IsPointer)
1056 ig.Emit (OpCodes.Ldind_I);
1058 ig.Emit (OpCodes.Ldind_Ref);
1062 // The stack contains the pointer and the value of type `type'
1064 public static void StoreFromPtr (ILGenerator ig, Type type)
1066 if (TypeManager.IsEnumType (type))
1067 type = TypeManager.EnumToUnderlying (type);
1068 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
1069 ig.Emit (OpCodes.Stind_I4);
1070 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
1071 ig.Emit (OpCodes.Stind_I8);
1072 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
1073 type == TypeManager.ushort_type)
1074 ig.Emit (OpCodes.Stind_I2);
1075 else if (type == TypeManager.float_type)
1076 ig.Emit (OpCodes.Stind_R4);
1077 else if (type == TypeManager.double_type)
1078 ig.Emit (OpCodes.Stind_R8);
1079 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
1080 type == TypeManager.bool_type)
1081 ig.Emit (OpCodes.Stind_I1);
1082 else if (type == TypeManager.intptr_type)
1083 ig.Emit (OpCodes.Stind_I);
1084 else if (type.IsValueType || TypeManager.IsGenericParameter (type))
1085 ig.Emit (OpCodes.Stobj, type);
1087 ig.Emit (OpCodes.Stind_Ref);
1091 // Returns the size of type `t' if known, otherwise, 0
1093 public static int GetTypeSize (Type t)
1095 t = TypeManager.TypeToCoreType (t);
1096 if (t == TypeManager.int32_type ||
1097 t == TypeManager.uint32_type ||
1098 t == TypeManager.float_type)
1100 else if (t == TypeManager.int64_type ||
1101 t == TypeManager.uint64_type ||
1102 t == TypeManager.double_type)
1104 else if (t == TypeManager.byte_type ||
1105 t == TypeManager.sbyte_type ||
1106 t == TypeManager.bool_type)
1108 else if (t == TypeManager.short_type ||
1109 t == TypeManager.char_type ||
1110 t == TypeManager.ushort_type)
1112 else if (t == TypeManager.decimal_type)
1118 public static void Error_NegativeArrayIndex (Location loc)
1120 Report.Error (248, loc, "Cannot create an array with a negative size");
1123 protected void Error_CannotCallAbstractBase (string name)
1125 Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
1129 // Converts `source' to an int, uint, long or ulong.
1131 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
1135 using (ec.With (EmitContext.Flags.CheckState, true)) {
1136 target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
1138 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
1140 target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
1142 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
1144 if (target == null) {
1145 source.Error_ValueCannotBeConverted (ec, loc, TypeManager.int32_type, false);
1151 // Only positive constants are allowed at compile time
1153 if (target is Constant){
1154 if (target is IntConstant){
1155 if (((IntConstant) target).Value < 0){
1156 Error_NegativeArrayIndex (loc);
1161 if (target is LongConstant){
1162 if (((LongConstant) target).Value < 0){
1163 Error_NegativeArrayIndex (loc);
1174 // Derived classes implement this method by cloning the fields that
1175 // could become altered during the Resolve stage
1177 // Only expressions that are created for the parser need to implement
1180 protected virtual void CloneTo (CloneContext clonectx, Expression target)
1182 throw new NotImplementedException (
1184 "CloneTo not implemented for expression {0}", this.GetType ()));
1188 // Clones an expression created by the parser.
1190 // We only support expressions created by the parser so far, not
1191 // expressions that have been resolved (many more classes would need
1192 // to implement CloneTo).
1194 // This infrastructure is here merely for Lambda expressions which
1195 // compile the same code using different type values for the same
1196 // arguments to find the correct overload
1198 public Expression Clone (CloneContext clonectx)
1200 Expression cloned = (Expression) MemberwiseClone ();
1201 CloneTo (clonectx, cloned);
1208 /// This is just a base class for expressions that can
1209 /// appear on statements (invocations, object creation,
1210 /// assignments, post/pre increment and decrement). The idea
1211 /// being that they would support an extra Emition interface that
1212 /// does not leave a result on the stack.
1214 public abstract class ExpressionStatement : Expression {
1216 public virtual ExpressionStatement ResolveStatement (EmitContext ec)
1218 Expression e = Resolve (ec);
1222 ExpressionStatement es = e as ExpressionStatement;
1224 Error_InvalidExpressionStatement ();
1230 /// Requests the expression to be emitted in a `statement'
1231 /// context. This means that no new value is left on the
1232 /// stack after invoking this method (constrasted with
1233 /// Emit that will always leave a value on the stack).
1235 public abstract void EmitStatement (EmitContext ec);
1239 /// This kind of cast is used to encapsulate the child
1240 /// whose type is child.Type into an expression that is
1241 /// reported to return "return_type". This is used to encapsulate
1242 /// expressions which have compatible types, but need to be dealt
1243 /// at higher levels with.
1245 /// For example, a "byte" expression could be encapsulated in one
1246 /// of these as an "unsigned int". The type for the expression
1247 /// would be "unsigned int".
1250 public class EmptyCast : Expression
1252 protected Expression child;
1254 protected EmptyCast (Expression child, Type return_type)
1256 eclass = child.eclass;
1257 loc = child.Location;
1262 public static Expression Create (Expression child, Type type)
1264 Constant c = child as Constant;
1266 return new EmptyConstantCast (c, type);
1268 return new EmptyCast (child, type);
1271 public override Expression DoResolve (EmitContext ec)
1273 // This should never be invoked, we are born in fully
1274 // initialized state.
1279 public override void Emit (EmitContext ec)
1284 public override bool GetAttributableValue (Type valueType, out object value)
1286 return child.GetAttributableValue (valueType, out value);
1289 protected override void CloneTo (CloneContext clonectx, Expression t)
1291 EmptyCast target = (EmptyCast) t;
1293 target.child = child.Clone (clonectx);
1298 /// Performs a cast using an operator (op_Explicit or op_Implicit)
1300 public class OperatorCast : EmptyCast {
1301 MethodInfo conversion_operator;
1304 public OperatorCast (Expression child, Type target_type) : this (child, target_type, false) {}
1306 public OperatorCast (Expression child, Type target_type, bool find_explicit)
1307 : base (child, target_type)
1309 this.find_explicit = find_explicit;
1312 // Returns the implicit operator that converts from
1313 // 'child.Type' to our target type (type)
1314 MethodInfo GetConversionOperator (bool find_explicit)
1316 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1320 mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberTypes.Method,
1321 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1324 mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1325 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1328 foreach (MethodInfo oper in mi) {
1329 ParameterData pd = TypeManager.GetParameterData (oper);
1331 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1339 public override void Emit (EmitContext ec)
1341 ILGenerator ig = ec.ig;
1344 conversion_operator = GetConversionOperator (find_explicit);
1346 if (conversion_operator == null)
1347 throw new InternalErrorException ("Outer conversion routine is out of sync");
1349 ig.Emit (OpCodes.Call, conversion_operator);
1355 /// This is a numeric cast to a Decimal
1357 public class CastToDecimal : EmptyCast {
1358 MethodInfo conversion_operator;
1360 public CastToDecimal (Expression child)
1361 : this (child, false)
1365 public CastToDecimal (Expression child, bool find_explicit)
1366 : base (child, TypeManager.decimal_type)
1368 conversion_operator = GetConversionOperator (find_explicit);
1370 if (conversion_operator == null)
1371 throw new InternalErrorException ("Outer conversion routine is out of sync");
1374 // Returns the implicit operator that converts from
1375 // 'child.Type' to System.Decimal.
1376 MethodInfo GetConversionOperator (bool find_explicit)
1378 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1380 MemberInfo [] mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method,
1381 BindingFlags.Static | BindingFlags.Public, operator_name, null);
1383 foreach (MethodInfo oper in mi) {
1384 ParameterData pd = TypeManager.GetParameterData (oper);
1386 if (pd.ParameterType (0) == child.Type && oper.ReturnType == type)
1392 public override void Emit (EmitContext ec)
1394 ILGenerator ig = ec.ig;
1397 ig.Emit (OpCodes.Call, conversion_operator);
1402 /// This is an explicit numeric cast from a Decimal
1404 public class CastFromDecimal : EmptyCast
1406 static IDictionary operators;
1408 public CastFromDecimal (Expression child, Type return_type)
1409 : base (child, return_type)
1411 if (child.Type != TypeManager.decimal_type)
1412 throw new InternalErrorException (
1413 "The expected type is Decimal, instead it is " + child.Type.FullName);
1416 // Returns the explicit operator that converts from an
1417 // express of type System.Decimal to 'type'.
1418 public Expression Resolve ()
1420 if (operators == null) {
1421 MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1422 TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method,
1423 BindingFlags.Static | BindingFlags.Public, "op_Explicit", null);
1425 operators = new System.Collections.Specialized.HybridDictionary ();
1426 foreach (MethodInfo oper in all_oper) {
1427 ParameterData pd = TypeManager.GetParameterData (oper);
1428 if (pd.ParameterType (0) == TypeManager.decimal_type)
1429 operators.Add (oper.ReturnType, oper);
1433 return operators.Contains (type) ? this : null;
1436 public override void Emit (EmitContext ec)
1438 ILGenerator ig = ec.ig;
1441 ig.Emit (OpCodes.Call, (MethodInfo)operators [type]);
1447 // Constant specialization of EmptyCast.
1448 // We need to special case this since an empty cast of
1449 // a constant is still a constant.
1451 public class EmptyConstantCast : Constant
1453 public readonly Constant child;
1455 public EmptyConstantCast(Constant child, Type type)
1456 : base (child.Location)
1458 eclass = child.eclass;
1463 public override string AsString ()
1465 return child.AsString ();
1468 public override object GetValue ()
1470 return child.GetValue ();
1473 public override Constant ConvertExplicitly (bool inCheckedContext, Type target_type)
1475 // FIXME: check that 'type' can be converted to 'target_type' first
1476 return child.ConvertExplicitly (inCheckedContext, target_type);
1479 public override Constant Increment ()
1481 return child.Increment ();
1484 public override bool IsDefaultValue {
1485 get { return child.IsDefaultValue; }
1488 public override bool IsNegative {
1489 get { return child.IsNegative; }
1492 public override bool IsZeroInteger {
1493 get { return child.IsZeroInteger; }
1496 public override void Emit (EmitContext ec)
1501 public override Constant ConvertImplicitly (Type target_type)
1503 // FIXME: Do we need to check user conversions?
1504 if (!Convert.ImplicitStandardConversionExists (this, target_type))
1506 return child.ConvertImplicitly (target_type);
1512 /// This class is used to wrap literals which belong inside Enums
1514 public class EnumConstant : Constant {
1515 public Constant Child;
1517 public EnumConstant (Constant child, Type enum_type):
1518 base (child.Location)
1520 eclass = child.eclass;
1525 public override Expression DoResolve (EmitContext ec)
1527 // This should never be invoked, we are born in fully
1528 // initialized state.
1533 public override void Emit (EmitContext ec)
1538 public override bool GetAttributableValue (Type valueType, out object value)
1540 value = GetTypedValue ();
1544 public override string GetSignatureForError()
1546 return TypeManager.CSharpName (Type);
1549 public override object GetValue ()
1551 return Child.GetValue ();
1554 public override object GetTypedValue ()
1556 // FIXME: runtime is not ready to work with just emited enums
1557 if (!RootContext.StdLib) {
1558 return Child.GetValue ();
1561 return System.Enum.ToObject (type, Child.GetValue ());
1564 public override string AsString ()
1566 return TypeManager.CSharpEnumValue (type, Child.GetValue ());
1569 public override Constant Increment()
1571 return new EnumConstant (Child.Increment (), type);
1574 public override bool IsDefaultValue {
1576 return Child.IsDefaultValue;
1580 public override bool IsZeroInteger {
1581 get { return Child.IsZeroInteger; }
1584 public override bool IsNegative {
1586 return Child.IsNegative;
1590 public override Constant ConvertExplicitly(bool inCheckedContext, Type target_type)
1592 if (Child.Type == target_type)
1595 return Child.ConvertExplicitly (inCheckedContext, target_type);
1598 public override Constant ConvertImplicitly (Type type)
1600 Type this_type = TypeManager.DropGenericTypeArguments (Type);
1601 type = TypeManager.DropGenericTypeArguments (type);
1603 if (this_type == type) {
1604 // This is workaround of mono bug. It can be removed when the latest corlib spreads enough
1605 if (TypeManager.IsEnumType (type.UnderlyingSystemType))
1608 Type child_type = TypeManager.DropGenericTypeArguments (Child.Type);
1609 if (type.UnderlyingSystemType != child_type)
1610 Child = Child.ConvertImplicitly (type.UnderlyingSystemType);
1614 if (!Convert.ImplicitStandardConversionExists (this, type)){
1618 return Child.ConvertImplicitly(type);
1624 /// This kind of cast is used to encapsulate Value Types in objects.
1626 /// The effect of it is to box the value type emitted by the previous
1629 public class BoxedCast : EmptyCast {
1631 public BoxedCast (Expression expr, Type target_type)
1632 : base (expr, target_type)
1634 eclass = ExprClass.Value;
1637 public override Expression DoResolve (EmitContext ec)
1639 // This should never be invoked, we are born in fully
1640 // initialized state.
1645 public override void Emit (EmitContext ec)
1649 ec.ig.Emit (OpCodes.Box, child.Type);
1653 public class UnboxCast : EmptyCast {
1654 public UnboxCast (Expression expr, Type return_type)
1655 : base (expr, return_type)
1659 public override Expression DoResolve (EmitContext ec)
1661 // This should never be invoked, we are born in fully
1662 // initialized state.
1667 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
1669 if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
1670 Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1671 return base.DoResolveLValue (ec, right_side);
1674 public override void Emit (EmitContext ec)
1677 ILGenerator ig = ec.ig;
1681 if (t.IsGenericParameter || t.IsGenericType && t.IsValueType)
1682 ig.Emit (OpCodes.Unbox_Any, t);
1686 ig.Emit (OpCodes.Unbox, t);
1688 LoadFromPtr (ig, t);
1694 /// This is used to perform explicit numeric conversions.
1696 /// Explicit numeric conversions might trigger exceptions in a checked
1697 /// context, so they should generate the conv.ovf opcodes instead of
1700 public class ConvCast : EmptyCast {
1701 public enum Mode : byte {
1702 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1704 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1705 U2_I1, U2_U1, U2_I2, U2_CH,
1706 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1707 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1708 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
1709 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
1710 CH_I1, CH_U1, CH_I2,
1711 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1712 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
1717 public ConvCast (Expression child, Type return_type, Mode m)
1718 : base (child, return_type)
1723 public override Expression DoResolve (EmitContext ec)
1725 // This should never be invoked, we are born in fully
1726 // initialized state.
1731 public override string ToString ()
1733 return String.Format ("ConvCast ({0}, {1})", mode, child);
1736 public override void Emit (EmitContext ec)
1738 ILGenerator ig = ec.ig;
1744 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1745 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1746 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1747 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1748 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1750 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1751 case Mode.U1_CH: /* nothing */ break;
1753 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1754 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1755 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1756 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1757 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1758 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1760 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1761 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1762 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1763 case Mode.U2_CH: /* nothing */ break;
1765 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1766 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1767 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1768 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1769 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1770 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1771 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1773 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1774 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1775 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1776 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1777 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1778 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1780 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1781 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1782 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1783 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1784 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1785 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1786 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1787 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1789 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1790 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1791 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1792 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1793 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1794 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1795 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1796 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1798 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1799 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1800 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1802 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1803 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1804 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1805 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1806 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1807 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1808 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1809 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1810 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1812 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
1813 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
1814 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
1815 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1816 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
1817 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
1818 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
1819 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
1820 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
1821 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1825 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
1826 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
1827 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
1828 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
1829 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
1831 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
1832 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
1834 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
1835 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
1836 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
1837 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
1838 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
1839 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
1841 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
1842 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
1843 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
1844 case Mode.U2_CH: /* nothing */ break;
1846 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
1847 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
1848 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
1849 case Mode.I4_U4: /* nothing */ break;
1850 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
1851 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
1852 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
1854 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
1855 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
1856 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
1857 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
1858 case Mode.U4_I4: /* nothing */ break;
1859 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
1861 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
1862 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
1863 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
1864 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
1865 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
1866 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
1867 case Mode.I8_U8: /* nothing */ break;
1868 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
1870 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
1871 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
1872 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
1873 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
1874 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
1875 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
1876 case Mode.U8_I8: /* nothing */ break;
1877 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
1879 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
1880 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
1881 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
1883 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
1884 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
1885 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
1886 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
1887 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
1888 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
1889 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
1890 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
1891 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
1893 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
1894 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
1895 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
1896 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
1897 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
1898 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
1899 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
1900 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
1901 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
1902 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
1908 public class OpcodeCast : EmptyCast {
1912 public OpcodeCast (Expression child, Type return_type, OpCode op)
1913 : base (child, return_type)
1917 second_valid = false;
1920 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1921 : base (child, return_type)
1926 second_valid = true;
1929 public override Expression DoResolve (EmitContext ec)
1931 // This should never be invoked, we are born in fully
1932 // initialized state.
1937 public override void Emit (EmitContext ec)
1948 /// This kind of cast is used to encapsulate a child and cast it
1949 /// to the class requested
1951 public class ClassCast : EmptyCast {
1952 public ClassCast (Expression child, Type return_type)
1953 : base (child, return_type)
1958 public override Expression DoResolve (EmitContext ec)
1960 // This should never be invoked, we are born in fully
1961 // initialized state.
1966 public override void Emit (EmitContext ec)
1970 if (TypeManager.IsGenericParameter (child.Type))
1971 ec.ig.Emit (OpCodes.Box, child.Type);
1974 if (type.IsGenericParameter)
1975 ec.ig.Emit (OpCodes.Unbox_Any, type);
1978 ec.ig.Emit (OpCodes.Castclass, type);
1983 /// SimpleName expressions are formed of a single word and only happen at the beginning
1984 /// of a dotted-name.
1986 public class SimpleName : Expression {
1987 public readonly string Name;
1988 public readonly TypeArguments Arguments;
1991 public SimpleName (string name, Location l)
1997 public SimpleName (string name, TypeArguments args, Location l)
2004 public SimpleName (string name, TypeParameter[] type_params, Location l)
2009 Arguments = new TypeArguments (l);
2010 foreach (TypeParameter type_param in type_params)
2011 Arguments.Add (new TypeParameterExpr (type_param, l));
2014 public static string RemoveGenericArity (string name)
2017 StringBuilder sb = null;
2019 int pos = name.IndexOf ('`', start);
2024 sb.Append (name.Substring (start));
2029 sb = new StringBuilder ();
2030 sb.Append (name.Substring (start, pos-start));
2033 while ((pos < name.Length) && Char.IsNumber (name [pos]))
2037 } while (start < name.Length);
2039 return sb.ToString ();
2042 public SimpleName GetMethodGroup ()
2044 return new SimpleName (RemoveGenericArity (Name), Arguments, loc);
2047 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
2049 if (ec.IsInFieldInitializer)
2050 Report.Error (236, l,
2051 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
2055 120, l, "`{0}': An object reference is required for the nonstatic field, method or property",
2059 public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc)
2061 return resolved_to != null && resolved_to.Type != null &&
2062 resolved_to.Type.Name == Name &&
2063 (ec.DeclContainer.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null);
2066 public override Expression DoResolve (EmitContext ec)
2068 return SimpleNameResolve (ec, null, false);
2071 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
2073 return SimpleNameResolve (ec, right_side, false);
2077 public Expression DoResolve (EmitContext ec, bool intermediate)
2079 return SimpleNameResolve (ec, null, intermediate);
2082 private bool IsNestedChild (Type t, Type parent)
2087 while (parent != null) {
2088 parent = TypeManager.DropGenericTypeArguments (parent);
2089 if (TypeManager.IsNestedChildOf (t, parent))
2092 parent = parent.BaseType;
2098 FullNamedExpression ResolveNested (IResolveContext ec, Type t)
2100 if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t))
2103 DeclSpace ds = ec.DeclContainer;
2104 while (ds != null) {
2105 if (IsNestedChild (t, ds.TypeBuilder))
2114 Type[] gen_params = TypeManager.GetTypeArguments (t);
2116 int arg_count = Arguments != null ? Arguments.Count : 0;
2118 for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) {
2119 if (arg_count + ds.CountTypeParameters == gen_params.Length) {
2120 TypeArguments new_args = new TypeArguments (loc);
2121 foreach (TypeParameter param in ds.TypeParameters)
2122 new_args.Add (new TypeParameterExpr (param, loc));
2124 if (Arguments != null)
2125 new_args.Add (Arguments);
2127 return new ConstructedType (t, new_args, loc);
2134 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2136 FullNamedExpression fne = ec.GenericDeclContainer.LookupGeneric (Name, loc);
2138 return fne.ResolveAsTypeStep (ec, silent);
2140 int errors = Report.Errors;
2141 fne = ec.DeclContainer.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false);
2144 if (fne.Type == null)
2147 FullNamedExpression nested = ResolveNested (ec, fne.Type);
2149 return nested.ResolveAsTypeStep (ec, false);
2151 if (Arguments != null) {
2152 ConstructedType ct = new ConstructedType (fne, Arguments, loc);
2153 return ct.ResolveAsTypeStep (ec, false);
2159 if (silent || errors != Report.Errors)
2162 Error_TypeOrNamespaceNotFound (ec);
2166 protected virtual void Error_TypeOrNamespaceNotFound (IResolveContext ec)
2168 MemberCore mc = ec.DeclContainer.GetDefinition (Name);
2170 Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
2174 string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
2175 string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
2176 foreach (Assembly a in RootNamespace.Global.Assemblies) {
2177 Type type = a.GetType (fullname);
2179 Report.SymbolRelatedToPreviousError (type);
2180 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type));
2185 Type t = ec.DeclContainer.LookupAnyGeneric (Name);
2187 Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
2191 if (Arguments != null) {
2192 FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
2193 if (retval != null) {
2194 Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc, "type");
2199 NamespaceEntry.Error_NamespaceNotFound (loc, Name);
2202 // TODO: I am still not convinced about this. If someone else will need it
2203 // implement this as virtual property in MemberCore hierarchy
2204 public static string GetMemberType (MemberCore mc)
2210 if (mc is FieldBase)
2212 if (mc is MethodCore)
2214 if (mc is EnumMember)
2222 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2228 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2234 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2241 /// 7.5.2: Simple Names.
2243 /// Local Variables and Parameters are handled at
2244 /// parse time, so they never occur as SimpleNames.
2246 /// The `intermediate' flag is used by MemberAccess only
2247 /// and it is used to inform us that it is ok for us to
2248 /// avoid the static check, because MemberAccess might end
2249 /// up resolving the Name as a Type name and the access as
2250 /// a static type access.
2252 /// ie: Type Type; .... { Type.GetType (""); }
2254 /// Type is both an instance variable and a Type; Type.GetType
2255 /// is the static method not an instance method of type.
2257 Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate)
2259 Expression e = null;
2262 // Stage 1: Performed by the parser (binding to locals or parameters).
2264 Block current_block = ec.CurrentBlock;
2265 if (current_block != null){
2266 LocalInfo vi = current_block.GetLocalInfo (Name);
2268 if (Arguments != null) {
2269 Report.Error (307, loc,
2270 "The variable `{0}' cannot be used with type arguments",
2275 LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2276 if (right_side != null) {
2277 return var.ResolveLValue (ec, right_side, loc);
2279 ResolveFlags rf = ResolveFlags.VariableOrValue;
2281 rf |= ResolveFlags.DisableFlowAnalysis;
2282 return var.Resolve (ec, rf);
2286 ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc);
2288 if (Arguments != null) {
2289 Report.Error (307, loc,
2290 "The variable `{0}' cannot be used with type arguments",
2295 if (right_side != null)
2296 return pref.ResolveLValue (ec, right_side, loc);
2298 return pref.Resolve (ec);
2301 Expression expr = current_block.Toplevel.GetTransparentIdentifier (Name);
2303 if (right_side != null)
2304 return expr.ResolveLValue (ec, right_side, loc);
2305 return expr.Resolve (ec);
2310 // Stage 2: Lookup members
2313 Type almost_matched_type = null;
2314 ArrayList almost_matched = null;
2315 for (DeclSpace lookup_ds = ec.DeclContainer; lookup_ds != null; lookup_ds = lookup_ds.Parent) {
2316 // either RootDeclSpace or GenericMethod
2317 if (lookup_ds.TypeBuilder == null)
2320 e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
2322 if (e is PropertyExpr) {
2323 // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
2324 // it doesn't know which accessor to check permissions against
2325 if (((PropertyExpr) e).IsAccessibleFrom (ec.ContainerType, right_side != null))
2327 } else if (e is EventExpr) {
2328 if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType))
2336 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2337 almost_matched_type = lookup_ds.TypeBuilder;
2338 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2343 if (almost_matched == null && almostMatchedMembers.Count > 0) {
2344 almost_matched_type = ec.ContainerType;
2345 almost_matched = (ArrayList) almostMatchedMembers.Clone ();
2347 e = ResolveAsTypeStep (ec, true);
2351 if (current_block != null) {
2352 IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
2354 LocalInfo li = ikv as LocalInfo;
2355 // Supress CS0219 warning
2359 Error_VariableIsUsedBeforeItIsDeclared (Name);
2364 if (almost_matched != null)
2365 almostMatchedMembers = almost_matched;
2366 if (almost_matched_type == null)
2367 almost_matched_type = ec.ContainerType;
2368 Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name,
2369 ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags);
2373 if (e is TypeExpr) {
2374 if (Arguments == null)
2377 ConstructedType ct = new ConstructedType (
2378 (FullNamedExpression) e, Arguments, loc);
2379 return ct.ResolveAsTypeStep (ec, false);
2382 if (e is MemberExpr) {
2383 MemberExpr me = (MemberExpr) e;
2386 if (me.IsInstance) {
2387 if (ec.IsStatic || ec.IsInFieldInitializer) {
2389 // Note that an MemberExpr can be both IsInstance and IsStatic.
2390 // An unresolved MethodGroupExpr can contain both kinds of methods
2391 // and each predicate is true if the MethodGroupExpr contains
2392 // at least one of that kind of method.
2396 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2397 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2398 return EmptyExpression.Null;
2402 // Pass the buck to MemberAccess and Invocation.
2404 left = EmptyExpression.Null;
2406 left = ec.GetThis (loc);
2409 left = new TypeExpression (ec.ContainerType, loc);
2412 e = me.ResolveMemberAccess (ec, left, loc, null);
2416 me = e as MemberExpr;
2420 if (Arguments != null) {
2421 MethodGroupExpr mg = me as MethodGroupExpr;
2425 return mg.ResolveGeneric (ec, Arguments);
2428 if (!me.IsStatic && (me.InstanceExpression != null) &&
2429 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2430 me.InstanceExpression.Type != me.DeclaringType &&
2431 !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2432 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2433 Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2434 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2438 return (right_side != null)
2439 ? me.DoResolveLValue (ec, right_side)
2440 : me.DoResolve (ec);
2446 public override void Emit (EmitContext ec)
2448 throw new InternalErrorException ("The resolve phase was not executed");
2451 public override string ToString ()
2456 public override string GetSignatureForError ()
2458 if (Arguments != null) {
2459 return TypeManager.RemoveGenericArity (Name) + "<" +
2460 Arguments.GetSignatureForError () + ">";
2466 protected override void CloneTo (CloneContext clonectx, Expression target)
2468 // CloneTo: Nothing, we do not keep any state on this expression
2473 /// Represents a namespace or a type. The name of the class was inspired by
2474 /// section 10.8.1 (Fully Qualified Names).
2476 public abstract class FullNamedExpression : Expression {
2477 public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2482 public abstract string FullName {
2488 /// Expression that evaluates to a type
2490 public abstract class TypeExpr : FullNamedExpression {
2491 override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
2493 TypeExpr t = DoResolveAsTypeStep (ec);
2497 eclass = ExprClass.Type;
2501 override public Expression DoResolve (EmitContext ec)
2503 return ResolveAsTypeTerminal (ec, false);
2506 override public void Emit (EmitContext ec)
2508 throw new Exception ("Should never be called");
2511 public virtual bool CheckAccessLevel (DeclSpace ds)
2513 return ds.CheckAccessLevel (Type);
2516 public virtual bool AsAccessible (DeclSpace ds, int flags)
2518 return ds.AsAccessible (Type, flags);
2521 public virtual bool IsClass {
2522 get { return Type.IsClass; }
2525 public virtual bool IsValueType {
2526 get { return Type.IsValueType; }
2529 public virtual bool IsInterface {
2530 get { return Type.IsInterface; }
2533 public virtual bool IsSealed {
2534 get { return Type.IsSealed; }
2537 public virtual bool CanInheritFrom ()
2539 if (Type == TypeManager.enum_type ||
2540 (Type == TypeManager.value_type && RootContext.StdLib) ||
2541 Type == TypeManager.multicast_delegate_type ||
2542 Type == TypeManager.delegate_type ||
2543 Type == TypeManager.array_type)
2549 protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec);
2551 public abstract string Name {
2555 public override bool Equals (object obj)
2557 TypeExpr tobj = obj as TypeExpr;
2561 return Type == tobj.Type;
2564 public override int GetHashCode ()
2566 return Type.GetHashCode ();
2569 public override string ToString ()
2576 /// Fully resolved Expression that already evaluated to a type
2578 public class TypeExpression : TypeExpr {
2579 public TypeExpression (Type t, Location l)
2582 eclass = ExprClass.Type;
2586 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2591 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2596 public override string Name {
2597 get { return Type.ToString (); }
2600 public override string FullName {
2601 get { return Type.FullName; }
2606 /// Used to create types from a fully qualified name. These are just used
2607 /// by the parser to setup the core types. A TypeLookupExpression is always
2608 /// classified as a type.
2610 public sealed class TypeLookupExpression : TypeExpr {
2611 readonly string name;
2613 public TypeLookupExpression (string name)
2616 eclass = ExprClass.Type;
2619 public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent)
2621 // It's null for corlib compilation only
2623 return DoResolveAsTypeStep (ec);
2628 private class UnexpectedType
2632 // This performes recursive type lookup, providing support for generic types.
2633 // For example, given the type:
2635 // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]]
2637 // The types will be checked in the following order:
2640 // System.Collections |
2641 // System.Collections.Generic |
2643 // System | recursive call 1 |
2644 // System.Int32 _| | main method call
2646 // System | recursive call 2 |
2647 // System.String _| |
2649 // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]] _|
2651 private Type TypeLookup (IResolveContext ec, string name)
2656 FullNamedExpression resolved = null;
2658 Type recursive_type = null;
2659 while (index < name.Length) {
2660 if (name[index] == '[') {
2665 if (name[index] == '[')
2667 else if (name[index] == ']')
2669 } while (braces > 0);
2670 recursive_type = TypeLookup (ec, name.Substring (open + 1, index - open - 1));
2671 if (recursive_type == null || (recursive_type == typeof(UnexpectedType)))
2672 return recursive_type;
2675 if (name[index] == ',')
2677 else if ((name[index] == '.' && !done) || (index == name.Length && name[0] != '[')) {
2678 string substring = name.Substring(dot, index - dot);
2680 if (resolved == null)
2681 resolved = RootNamespace.Global.Lookup (ec.DeclContainer, substring, Location.Null);
2682 else if (resolved is Namespace)
2683 resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null);
2684 else if (type != null)
2685 type = TypeManager.GetNestedType (type, substring);
2689 if (resolved == null)
2691 else if (type == null && resolved is TypeExpr)
2692 type = resolved.Type;
2699 if (name[0] != '[') {
2700 string substring = name.Substring(dot, index - dot);
2703 return TypeManager.GetNestedType (type, substring);
2705 if (resolved != null) {
2706 resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null);
2707 if (resolved is TypeExpr)
2708 return resolved.Type;
2710 if (resolved == null)
2713 resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
2714 return typeof (UnexpectedType);
2720 return recursive_type;
2723 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2725 Type t = TypeLookup (ec, name);
2727 NamespaceEntry.Error_NamespaceNotFound (loc, name);
2730 if (t == typeof(UnexpectedType))
2736 public override string Name {
2737 get { return name; }
2740 public override string FullName {
2741 get { return name; }
2744 protected override void CloneTo (CloneContext clonectx, Expression target)
2746 // CloneTo: Nothing, we do not keep any state on this expression
2749 public override string GetSignatureForError ()
2752 return TypeManager.CSharpName (name);
2754 return base.GetSignatureForError ();
2759 /// Represents an "unbound generic type", ie. typeof (Foo<>).
2762 public class UnboundTypeExpression : TypeExpr
2766 public UnboundTypeExpression (MemberName name, Location l)
2772 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2775 if (name.Left != null) {
2776 Expression lexpr = name.Left.GetTypeExpression ();
2777 expr = new MemberAccess (lexpr, name.Basename);
2779 expr = new SimpleName (name.Basename, loc);
2782 FullNamedExpression fne = expr.ResolveAsTypeStep (ec, false);
2787 return new TypeExpression (type, loc);
2790 public override string Name {
2791 get { return name.FullName; }
2794 public override string FullName {
2795 get { return name.FullName; }
2799 public class TypeAliasExpression : TypeExpr {
2800 FullNamedExpression alias;
2805 public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l)
2811 eclass = ExprClass.Type;
2813 name = alias.FullName + "<" + args.ToString () + ">";
2815 name = alias.FullName;
2818 public override string Name {
2819 get { return alias.FullName; }
2822 public override string FullName {
2823 get { return name; }
2826 protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
2828 texpr = alias.ResolveAsTypeTerminal (ec, false);
2832 Type type = texpr.Type;
2833 int num_args = TypeManager.GetNumberOfTypeArguments (type);
2836 if (num_args == 0) {
2837 Report.Error (308, loc,
2838 "The non-generic type `{0}' cannot " +
2839 "be used with type arguments.",
2840 TypeManager.CSharpName (type));
2844 ConstructedType ctype = new ConstructedType (type, args, loc);
2845 return ctype.ResolveAsTypeTerminal (ec, false);
2846 } else if (num_args > 0) {
2847 Report.Error (305, loc,
2848 "Using the generic type `{0}' " +
2849 "requires {1} type arguments",
2850 TypeManager.CSharpName (type), num_args.ToString ());
2857 public override bool CheckAccessLevel (DeclSpace ds)
2859 return texpr.CheckAccessLevel (ds);
2862 public override bool AsAccessible (DeclSpace ds, int flags)
2864 return texpr.AsAccessible (ds, flags);
2867 public override bool IsClass {
2868 get { return texpr.IsClass; }
2871 public override bool IsValueType {
2872 get { return texpr.IsValueType; }
2875 public override bool IsInterface {
2876 get { return texpr.IsInterface; }
2879 public override bool IsSealed {
2880 get { return texpr.IsSealed; }
2885 /// This class denotes an expression which evaluates to a member
2886 /// of a struct or a class.
2888 public abstract class MemberExpr : Expression
2891 /// The name of this member.
2893 public abstract string Name {
2898 /// Whether this is an instance member.
2900 public abstract bool IsInstance {
2905 /// Whether this is a static member.
2907 public abstract bool IsStatic {
2912 /// The type which declares this member.
2914 public abstract Type DeclaringType {
2919 /// The instance expression associated with this member, if it's a
2920 /// non-static member.
2922 public Expression InstanceExpression;
2924 public static void error176 (Location loc, string name)
2926 Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2927 "with an instance reference, qualify it with a type name instead", name);
2930 // TODO: possible optimalization
2931 // Cache resolved constant result in FieldBuilder <-> expression map
2932 public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
2933 SimpleName original)
2937 // original == null || original.Resolve (...) ==> left
2940 if (left is TypeExpr) {
2941 left = left.ResolveAsTypeTerminal (ec, true);
2946 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2954 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2957 error176 (loc, GetSignatureForError ());
2961 InstanceExpression = left;
2966 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2971 if (InstanceExpression == EmptyExpression.Null) {
2972 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2976 if (InstanceExpression.Type.IsValueType) {
2977 if (InstanceExpression is IMemoryLocation) {
2978 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2980 LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
2981 InstanceExpression.Emit (ec);
2983 t.AddressOf (ec, AddressOp.Store);
2986 InstanceExpression.Emit (ec);
2988 if (prepare_for_load)
2989 ec.ig.Emit (OpCodes.Dup);
2994 /// Represents group of extension methods
2996 public class ExtensionMethodGroupExpr : MethodGroupExpr
2998 readonly NamespaceEntry namespaceEntry;
2999 public Expression ExtensionExpression;
3000 Argument extension_argument;
3002 public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l)
3003 : base (list, extensionType, l)
3005 this.namespaceEntry = n;
3008 public override bool IsBase {
3009 get { return true; }
3012 public override bool IsStatic {
3013 get { return true; }
3016 public bool IsTopLevel {
3017 get { return namespaceEntry == null; }
3020 public override void EmitArguments (EmitContext ec, ArrayList arguments)
3022 if (arguments == null)
3023 arguments = new ArrayList (1);
3024 arguments.Insert (0, extension_argument);
3025 base.EmitArguments (ec, arguments);
3028 public override void EmitCall (EmitContext ec, ArrayList arguments)
3030 if (arguments == null)
3031 arguments = new ArrayList (1);
3032 arguments.Insert (0, extension_argument);
3033 base.EmitCall (ec, arguments);
3036 public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc)
3038 if ((ExtensionExpression.eclass & (ExprClass.Value | ExprClass.Variable)) == 0)
3039 return base.OverloadResolve (ec, arguments, may_fail, loc);
3041 if (arguments == null)
3042 arguments = new ArrayList (1);
3044 arguments.Insert (0, new Argument (ExtensionExpression));
3045 MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespaceEntry, loc);
3047 // Store resolved argument and restore original arguments
3049 ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0];
3050 arguments.RemoveAt (0);
3056 return base.OverloadResolve (ec, arguments, may_fail, loc);
3061 MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
3063 // Use normal resolve rules
3064 MethodGroupExpr mg = base.OverloadResolve (ec, arguments, true, loc);
3072 ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name);
3076 e.ExtensionExpression = ExtensionExpression;
3077 return e.ResolveOverloadExtensions (ec, arguments, e.namespaceEntry, loc);
3082 /// MethodGroupExpr represents a group of method candidates which
3083 /// can be resolved to the best method overload
3085 public class MethodGroupExpr : MemberExpr {
3086 public MethodBase [] Methods;
3087 MethodBase best_candidate;
3088 bool has_type_arguments;
3089 bool identical_type_name;
3092 public MethodGroupExpr (MemberInfo [] mi, Type type, Location l)
3095 Methods = new MethodBase [mi.Length];
3096 mi.CopyTo (Methods, 0);
3099 public MethodGroupExpr (ArrayList list, Type type, Location l)
3103 Methods = (MethodBase[])list.ToArray (typeof (MethodBase));
3105 foreach (MemberInfo m in list){
3106 if (!(m is MethodBase)){
3107 Console.WriteLine ("Name " + m.Name);
3108 Console.WriteLine ("Found a: " + m.GetType ().FullName);
3117 protected MethodGroupExpr (Type type, Location loc)
3120 eclass = ExprClass.MethodGroup;
3124 public override Type DeclaringType {
3127 // We assume that the top-level type is in the end
3129 return Methods [Methods.Length - 1].DeclaringType;
3130 //return Methods [0].DeclaringType;
3134 public bool HasTypeArguments {
3136 return has_type_arguments;
3140 public bool IdenticalTypeName {
3142 return identical_type_name;
3146 identical_type_name = value;
3150 public virtual bool IsBase {
3159 public override string GetSignatureForError ()
3161 if (best_candidate != null)
3162 return TypeManager.CSharpSignature (best_candidate);
3164 return TypeManager.CSharpSignature (Methods [0]);
3167 public override string Name {
3169 return Methods [0].Name;
3173 public override bool IsInstance {
3175 foreach (MethodBase mb in Methods)
3183 public override bool IsStatic {
3185 foreach (MethodBase mb in Methods)
3193 public static explicit operator ConstructorInfo (MethodGroupExpr mg)
3195 return (ConstructorInfo)mg.best_candidate;
3198 public static explicit operator MethodInfo (MethodGroupExpr mg)
3200 return (MethodInfo)mg.best_candidate;
3204 /// Determines "better conversion" as specified in 14.4.2.3
3206 /// Returns : p if a->p is better,
3207 /// q if a->q is better,
3208 /// null if neither is better
3210 static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q)
3212 Type argument_type = TypeManager.TypeToCoreType (a.Type);
3213 Expression argument_expr = a.Expr;
3215 if (argument_type == null)
3216 throw new Exception ("Expression of type " + a.Expr +
3217 " does not resolve its type");
3219 if (p == null || q == null)
3220 throw new InternalErrorException ("BetterConversion Got a null conversion");
3225 if (argument_expr is NullLiteral)
3228 // If the argument is null and one of the types to compare is 'object' and
3229 // the other is a reference type, we prefer the other.
3231 // This follows from the usual rules:
3232 // * There is an implicit conversion from 'null' to type 'object'
3233 // * There is an implicit conversion from 'null' to any reference type
3234 // * There is an implicit conversion from any reference type to type 'object'
3235 // * There is no implicit conversion from type 'object' to other reference types
3236 // => Conversion of 'null' to a reference type is better than conversion to 'object'
3238 // FIXME: This probably isn't necessary, since the type of a NullLiteral is the
3239 // null type. I think it used to be 'object' and thus needed a special
3240 // case to avoid the immediately following two checks.
3242 if (!p.IsValueType && q == TypeManager.object_type)
3244 if (!q.IsValueType && p == TypeManager.object_type)
3248 if (argument_type == p)
3251 if (argument_type == q)
3254 Expression p_tmp = new EmptyExpression (p);
3255 Expression q_tmp = new EmptyExpression (q);
3257 bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
3258 bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
3260 if (p_to_q && !q_to_p)
3263 if (q_to_p && !p_to_q)
3266 if (p == TypeManager.sbyte_type)
3267 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
3268 q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3270 if (q == TypeManager.sbyte_type)
3271 if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
3272 p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3275 if (p == TypeManager.short_type)
3276 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
3277 q == TypeManager.uint64_type)
3279 if (q == TypeManager.short_type)
3280 if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
3281 p == TypeManager.uint64_type)
3284 if (p == TypeManager.int32_type)
3285 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3287 if (q == TypeManager.int32_type)
3288 if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3291 if (p == TypeManager.int64_type)
3292 if (q == TypeManager.uint64_type)
3294 if (q == TypeManager.int64_type)
3295 if (p == TypeManager.uint64_type)
3302 /// Determines "Better function" between candidate
3303 /// and the current best match
3306 /// Returns a boolean indicating :
3307 /// false if candidate ain't better
3308 /// true if candidate is better than the current best match
3310 static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
3311 MethodBase candidate, bool candidate_params,
3312 MethodBase best, bool best_params)
3314 ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
3315 ParameterData best_pd = TypeManager.GetParameterData (best);
3317 bool better_at_least_one = false;
3319 for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx)
3321 Argument a = (Argument) args [j];
3323 Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (c_idx));
3324 Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (b_idx));
3326 if (candidate_params && candidate_pd.ParameterModifier (c_idx) == Parameter.Modifier.PARAMS)
3328 ct = TypeManager.GetElementType (ct);
3332 if (best_params && best_pd.ParameterModifier (b_idx) == Parameter.Modifier.PARAMS)
3334 bt = TypeManager.GetElementType (bt);
3342 Type better = BetterConversion (ec, a, ct, bt);
3344 // for each argument, the conversion to 'ct' should be no worse than
3345 // the conversion to 'bt'.
3349 // for at least one argument, the conversion to 'ct' should be better than
3350 // the conversion to 'bt'.
3352 better_at_least_one = true;
3355 if (better_at_least_one)
3359 // This handles the case
3361 // Add (float f1, float f2, float f3);
3362 // Add (params decimal [] foo);
3364 // The call Add (3, 4, 5) should be ambiguous. Without this check, the
3365 // first candidate would've chosen as better.
3371 // The two methods have equal parameter types. Now apply tie-breaking rules
3373 if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
3375 if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
3379 // This handles the following cases:
3381 // Trim () is better than Trim (params char[] chars)
3382 // Concat (string s1, string s2, string s3) is better than
3383 // Concat (string s1, params string [] srest)
3384 // Foo (int, params int [] rest) is better than Foo (params int [] rest)
3386 if (!candidate_params && best_params)
3388 if (candidate_params && !best_params)
3391 int candidate_param_count = candidate_pd.Count;
3392 int best_param_count = best_pd.Count;
3394 if (candidate_param_count != best_param_count)
3395 // can only happen if (candidate_params && best_params)
3396 return candidate_param_count > best_param_count;
3399 // now, both methods have the same number of parameters, and the parameters have the same types
3400 // Pick the "more specific" signature
3403 MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate);
3404 MethodBase orig_best = TypeManager.DropGenericMethodArguments (best);
3406 ParameterData orig_candidate_pd = TypeManager.GetParameterData (orig_candidate);
3407 ParameterData orig_best_pd = TypeManager.GetParameterData (orig_best);
3409 bool specific_at_least_once = false;
3410 for (int j = 0; j < candidate_param_count; ++j)
3412 Type ct = TypeManager.TypeToCoreType (orig_candidate_pd.ParameterType (j));
3413 Type bt = TypeManager.TypeToCoreType (orig_best_pd.ParameterType (j));
3416 Type specific = MoreSpecific (ct, bt);
3420 specific_at_least_once = true;
3423 if (specific_at_least_once)
3426 // FIXME: handle lifted operators
3432 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
3433 SimpleName original)
3435 if (!(left is TypeExpr) &&
3436 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
3437 IdenticalTypeName = true;
3439 return base.ResolveMemberAccess (ec, left, loc, original);
3442 override public Expression DoResolve (EmitContext ec)
3444 if (InstanceExpression != null) {
3445 InstanceExpression = InstanceExpression.DoResolve (ec);
3446 if (InstanceExpression == null)
3453 public void ReportUsageError ()
3455 Report.Error (654, loc, "Method `" + DeclaringType + "." +
3456 Name + "()' is referenced without parentheses");
3459 override public void Emit (EmitContext ec)
3461 ReportUsageError ();
3464 public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
3466 Invocation.EmitArguments (ec, best_candidate, arguments, false, null);
3469 public virtual void EmitCall (EmitContext ec, ArrayList arguments)
3471 Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);
3474 protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method,
3475 Type delegate_type, Argument a, ParameterData expected_par)
3477 if (a is CollectionElementInitializer.ElementInitializerArgument) {
3478 Report.SymbolRelatedToPreviousError (method);
3479 if ((expected_par.ParameterModifier (idx) & Parameter.Modifier.ISBYREF) != 0) {
3480 Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
3481 TypeManager.CSharpSignature (method));
3484 Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
3485 TypeManager.CSharpSignature (method));
3486 } else if (delegate_type == null) {
3487 Report.SymbolRelatedToPreviousError (method);
3488 Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
3489 TypeManager.CSharpSignature (method));
3491 Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
3492 TypeManager.CSharpName (delegate_type));
3494 Parameter.Modifier mod = expected_par.ParameterModifier (idx);
3496 string index = (idx + 1).ToString ();
3497 if ((a.Modifier & Parameter.Modifier.ISBYREF) != 0 && mod != a.Modifier) {
3498 if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0)
3499 Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword",
3500 index, Parameter.GetModifierSignature (a.Modifier));
3502 Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
3503 index, Parameter.GetModifierSignature (mod));
3505 string p1 = Argument.FullDesc (a);
3506 string p2 = TypeManager.CSharpName (expected_par.ParameterType (idx));
3509 Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
3510 Report.SymbolRelatedToPreviousError (a.Expr.Type);
3511 Report.SymbolRelatedToPreviousError (expected_par.ParameterType (idx));
3513 Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2);
3517 public static bool IsAncestralType (Type first_type, Type second_type)
3519 return first_type != second_type &&
3520 (TypeManager.IsSubclassOf (second_type, first_type) ||
3521 TypeManager.ImplementsInterface (second_type, first_type));
3524 public bool IsApplicable (EmitContext ec,
3525 ArrayList arguments, int arg_count, ref MethodBase method)
3527 MethodBase candidate = method;
3530 if (!HasTypeArguments &&
3531 !TypeManager.InferTypeArguments (ec, arguments, ref candidate))
3534 if (TypeManager.IsGenericMethodDefinition (candidate))
3535 throw new InternalErrorException ("a generic method definition took part in overload resolution");
3538 if (IsApplicable (ec, arguments, arg_count, candidate)) {
3546 protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
3548 return parameters.Count;
3552 /// Determines if the candidate method is applicable (section 14.4.2.1)
3553 /// to the given set of arguments
3555 bool IsApplicable (EmitContext ec, ArrayList arguments, int arg_count,
3556 MethodBase candidate)
3558 ParameterData pd = TypeManager.GetParameterData (candidate);
3559 int param_count = GetApplicableParametersCount (candidate, pd);
3561 if (arg_count != param_count)
3564 for (int i = arg_count; i > 0; ) {
3567 Argument a = (Argument) arguments [i];
3569 Parameter.Modifier a_mod = a.Modifier &
3570 ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
3572 Parameter.Modifier p_mod = pd.ParameterModifier (i) &
3573 ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS);
3578 Type pt = pd.ParameterType (i);
3579 if (TypeManager.IsEqual (pt, a.Type))
3582 if (a_mod != Parameter.Modifier.NONE)
3585 // FIXME: Kill this abomination (EmitContext.TempEc)
3586 EmitContext prevec = EmitContext.TempEc;
3587 EmitContext.TempEc = ec;
3589 if (!Convert.ImplicitConversionExists (ec, a.Expr, pt))
3592 EmitContext.TempEc = prevec;
3599 public static bool IsOverride (MethodBase cand_method, MethodBase base_method)
3601 if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType))
3604 ParameterData cand_pd = TypeManager.GetParameterData (cand_method);
3605 ParameterData base_pd = TypeManager.GetParameterData (base_method);
3607 if (cand_pd.Count != base_pd.Count)
3610 for (int j = 0; j < cand_pd.Count; ++j)
3612 Parameter.Modifier cm = cand_pd.ParameterModifier (j);
3613 Parameter.Modifier bm = base_pd.ParameterModifier (j);
3614 Type ct = TypeManager.TypeToCoreType (cand_pd.ParameterType (j));
3615 Type bt = TypeManager.TypeToCoreType (base_pd.ParameterType (j));
3617 if (cm != bm || ct != bt)
3624 public bool IsParamsMethodApplicable (EmitContext ec,
3625 ArrayList arguments, int arg_count,
3626 ref MethodBase candidate)
3628 return IsParamsMethodApplicable (
3629 ec, arguments, arg_count, false, ref candidate) ||
3630 IsParamsMethodApplicable (
3631 ec, arguments, arg_count, true, ref candidate);
3636 bool IsParamsMethodApplicable (EmitContext ec,
3637 ArrayList arguments, int arg_count,
3638 bool do_varargs, ref MethodBase candidate)
3641 if (!HasTypeArguments &&
3642 !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate))
3645 if (TypeManager.IsGenericMethodDefinition (candidate))
3646 throw new InternalErrorException ("a generic method definition took part in overload resolution");
3649 return IsParamsMethodApplicable (
3650 ec, arguments, arg_count, candidate, do_varargs);
3654 /// Determines if the candidate method, if a params method, is applicable
3655 /// in its expanded form to the given set of arguments
3657 bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
3658 int arg_count, MethodBase candidate,
3661 ParameterData pd = TypeManager.GetParameterData (candidate);
3662 int pd_count = GetApplicableParametersCount (candidate, pd);
3666 int count = pd_count - 1;
3668 if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
3670 if (pd_count != arg_count)
3673 if (!(((Argument) arguments [count]).Expr is Arglist))
3681 if (count > arg_count)
3684 if (pd_count == 1 && arg_count == 0)
3688 // If we have come this far, the case which
3689 // remains is when the number of parameters is
3690 // less than or equal to the argument count.
3692 int argument_index = 0;
3694 for (int i = 0; i < pd_count; ++i) {
3696 if ((pd.ParameterModifier (i) & Parameter.Modifier.PARAMS) != 0) {
3697 Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
3698 int params_args_count = arg_count - pd_count;
3699 if (params_args_count < 0)
3703 a = (Argument) arguments [argument_index++];
3705 if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
3707 } while (params_args_count-- > 0);
3711 a = (Argument) arguments [argument_index++];
3713 Parameter.Modifier a_mod = a.Modifier &
3714 (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
3715 Parameter.Modifier p_mod = pd.ParameterModifier (i) &
3716 (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
3718 if (a_mod == p_mod) {
3720 if (a_mod == Parameter.Modifier.NONE)
3721 if (!Convert.ImplicitConversionExists (ec,
3723 pd.ParameterType (i)))
3726 if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
3727 Type pt = pd.ParameterType (i);
3730 pt = TypeManager.GetReferenceType (pt);
3743 public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
3745 MemberInfo [] miset;
3746 MethodGroupExpr union;
3751 return (MethodGroupExpr) mg2;
3754 return (MethodGroupExpr) mg1;
3757 MethodGroupExpr left_set = null, right_set = null;
3758 int length1 = 0, length2 = 0;
3760 left_set = (MethodGroupExpr) mg1;
3761 length1 = left_set.Methods.Length;
3763 right_set = (MethodGroupExpr) mg2;
3764 length2 = right_set.Methods.Length;
3766 ArrayList common = new ArrayList ();
3768 foreach (MethodBase r in right_set.Methods){
3769 if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
3773 miset = new MemberInfo [length1 + length2 - common.Count];
3774 left_set.Methods.CopyTo (miset, 0);
3778 foreach (MethodBase r in right_set.Methods) {
3779 if (!common.Contains (r))
3783 union = new MethodGroupExpr (miset, mg1.Type, loc);
3788 static Type MoreSpecific (Type p, Type q)
3790 if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
3792 if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
3795 if (TypeManager.HasElementType (p))
3797 Type pe = TypeManager.GetElementType (p);
3798 Type qe = TypeManager.GetElementType (q);
3799 Type specific = MoreSpecific (pe, qe);
3805 else if (TypeManager.IsGenericType (p))
3807 Type[] pargs = TypeManager.GetTypeArguments (p);
3808 Type[] qargs = TypeManager.GetTypeArguments (q);
3810 bool p_specific_at_least_once = false;
3811 bool q_specific_at_least_once = false;
3813 for (int i = 0; i < pargs.Length; i++)
3815 Type specific = MoreSpecific (pargs [i], qargs [i]);
3816 if (specific == pargs [i])
3817 p_specific_at_least_once = true;
3818 if (specific == qargs [i])
3819 q_specific_at_least_once = true;
3822 if (p_specific_at_least_once && !q_specific_at_least_once)
3824 if (!p_specific_at_least_once && q_specific_at_least_once)
3832 /// Find the Applicable Function Members (7.4.2.1)
3834 /// me: Method Group expression with the members to select.
3835 /// it might contain constructors or methods (or anything
3836 /// that maps to a method).
3838 /// Arguments: ArrayList containing resolved Argument objects.
3840 /// loc: The location if we want an error to be reported, or a Null
3841 /// location for "probing" purposes.
3843 /// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
3844 /// that is the best match of me on Arguments.
3847 public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments,
3848 bool may_fail, Location loc)
3850 bool method_params = false;
3851 Type applicable_type = null;
3853 ArrayList candidates = new ArrayList (2);
3854 ArrayList candidate_overrides = null;
3857 // Used to keep a map between the candidate
3858 // and whether it is being considered in its
3859 // normal or expanded form
3861 // false is normal form, true is expanded form
3863 Hashtable candidate_to_form = null;
3865 if (Arguments != null)
3866 arg_count = Arguments.Count;
3868 if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
3870 Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
3874 int nmethods = Methods.Length;
3878 // Methods marked 'override' don't take part in 'applicable_type'
3879 // computation, nor in the actual overload resolution.
3880 // However, they still need to be emitted instead of a base virtual method.
3881 // So, we salt them away into the 'candidate_overrides' array.
3883 // In case of reflected methods, we replace each overriding method with
3884 // its corresponding base virtual method. This is to improve compatibility
3885 // with non-C# libraries which change the visibility of overrides (#75636)
3888 for (int i = 0; i < Methods.Length; ++i) {
3889 MethodBase m = Methods [i];
3891 Type [] gen_args = null;
3892 if (m.IsGenericMethod && !m.IsGenericMethodDefinition)
3893 gen_args = m.GetGenericArguments ();
3895 if (TypeManager.IsOverride (m)) {
3896 if (candidate_overrides == null)
3897 candidate_overrides = new ArrayList ();
3898 candidate_overrides.Add (m);
3899 m = TypeManager.TryGetBaseDefinition (m);
3901 if (m != null && gen_args != null) {
3902 if (!m.IsGenericMethodDefinition)
3903 throw new InternalErrorException ("GetBaseDefinition didn't return a GenericMethodDefinition");
3904 m = ((MethodInfo) m).MakeGenericMethod (gen_args);
3914 int applicable_errors = Report.Errors;
3917 // First we construct the set of applicable methods
3919 bool is_sorted = true;
3920 for (int i = 0; i < nmethods; i++) {
3921 Type decl_type = Methods [i].DeclaringType;
3924 // If we have already found an applicable method
3925 // we eliminate all base types (Section 14.5.5.1)
3927 if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
3931 // Check if candidate is applicable (section 14.4.2.1)
3932 // Is candidate applicable in normal form?
3934 bool is_applicable = IsApplicable (ec, Arguments, arg_count, ref Methods [i]);
3936 if (!is_applicable && IsParamsMethodApplicable (ec, Arguments, arg_count, ref Methods [i])) {
3937 MethodBase candidate = Methods [i];
3938 if (candidate_to_form == null)
3939 candidate_to_form = new PtrHashtable ();
3940 candidate_to_form [candidate] = candidate;
3941 // Candidate is applicable in expanded form
3942 is_applicable = true;
3948 candidates.Add (Methods [i]);
3950 if (applicable_type == null)
3951 applicable_type = decl_type;
3952 else if (applicable_type != decl_type) {
3954 if (IsAncestralType (applicable_type, decl_type))
3955 applicable_type = decl_type;
3959 if (applicable_errors != Report.Errors)
3962 int candidate_top = candidates.Count;
3964 if (applicable_type == null) {
3965 if (ec.IsInProbingMode)
3969 // Okay so we have failed to find anything so we
3970 // return by providing info about the closest match
3972 int errors = Report.Errors;
3973 for (int i = 0; i < nmethods; ++i) {
3974 MethodBase c = Methods [i];
3975 ParameterData pd = TypeManager.GetParameterData (c);
3977 if (pd.Count != arg_count)
3981 if (!TypeManager.InferTypeArguments (ec, Arguments, ref c))
3983 if (TypeManager.IsGenericMethodDefinition (c))
3987 VerifyArgumentsCompat (ec, Arguments, arg_count,
3988 c, false, null, may_fail, loc);
3990 if (!may_fail && errors == Report.Errors){
3992 throw new InternalErrorException (
3993 "VerifyArgumentsCompat and IsApplicable do not agree; " +
3994 "likely reason: ImplicitConversion and ImplicitConversionExists have gone out of sync");
4000 if (!may_fail && errors == Report.Errors) {
4001 string report_name = Name;
4002 if (report_name == ".ctor")
4003 report_name = TypeManager.CSharpName (DeclaringType);
4009 for (int i = 0; i < Methods.Length; ++i) {
4010 MethodBase c = Methods [i];
4011 ParameterData pd = TypeManager.GetParameterData (c);
4013 if (pd.Count != arg_count)
4016 if (TypeManager.InferTypeArguments (ec, Arguments, ref c))
4020 411, loc, "The type arguments for " +
4021 "method `{0}' cannot be inferred from " +
4022 "the usage. Try specifying the type " +
4023 "arguments explicitly", TypeManager.CSharpSignature (c));
4028 if (Name == ConstructorInfo.ConstructorName) {
4029 if (almostMatchedMembers.Count != 0) {
4030 Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor",
4031 null, MemberTypes.Constructor, AllBindingFlags);
4033 Report.SymbolRelatedToPreviousError (type);
4034 Report.Error (1729, loc,
4035 "The type `{0}' does not contain a constructor that takes `{1}' arguments",
4036 TypeManager.CSharpName (type), arg_count);
4039 Invocation.Error_WrongNumArguments (loc, report_name, arg_count);
4048 // At this point, applicable_type is _one_ of the most derived types
4049 // in the set of types containing the methods in this MethodGroup.
4050 // Filter the candidates so that they only contain methods from the
4051 // most derived types.
4054 int finalized = 0; // Number of finalized candidates
4057 // Invariant: applicable_type is a most derived type
4059 // We'll try to complete Section 14.5.5.1 for 'applicable_type' by
4060 // eliminating all it's base types. At the same time, we'll also move
4061 // every unrelated type to the end of the array, and pick the next
4062 // 'applicable_type'.
4064 Type next_applicable_type = null;
4065 int j = finalized; // where to put the next finalized candidate
4066 int k = finalized; // where to put the next undiscarded candidate
4067 for (int i = finalized; i < candidate_top; ++i) {
4068 MethodBase candidate = (MethodBase) candidates [i];
4069 Type decl_type = candidate.DeclaringType;
4071 if (decl_type == applicable_type) {
4072 candidates [k++] = candidates [j];
4073 candidates [j++] = candidates [i];
4077 if (IsAncestralType (decl_type, applicable_type))
4080 if (next_applicable_type != null &&
4081 IsAncestralType (decl_type, next_applicable_type))
4084 candidates [k++] = candidates [i];
4086 if (next_applicable_type == null ||
4087 IsAncestralType (next_applicable_type, decl_type))
4088 next_applicable_type = decl_type;
4091 applicable_type = next_applicable_type;
4094 } while (applicable_type != null);
4098 // Now we actually find the best method
4101 best_candidate = (MethodBase) candidates [0];
4102 method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
4103 for (int ix = 1; ix < candidate_top; ix++) {
4104 MethodBase candidate = (MethodBase) candidates [ix];
4106 if (candidate == best_candidate)
4109 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4111 if (BetterFunction (ec, Arguments, arg_count,
4112 candidate, cand_params,
4113 best_candidate, method_params)) {
4114 best_candidate = candidate;
4115 method_params = cand_params;
4119 // Now check that there are no ambiguities i.e the selected method
4120 // should be better than all the others
4122 MethodBase ambiguous = null;
4123 for (int ix = 0; ix < candidate_top; ix++) {
4124 MethodBase candidate = (MethodBase) candidates [ix];
4126 if (candidate == best_candidate)
4129 bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
4130 if (!BetterFunction (ec, Arguments, arg_count,
4131 best_candidate, method_params,
4132 candidate, cand_params))
4135 Report.SymbolRelatedToPreviousError (candidate);
4136 ambiguous = candidate;
4140 if (ambiguous != null) {
4141 Report.SymbolRelatedToPreviousError (best_candidate);
4142 Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
4143 TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
4148 // If the method is a virtual function, pick an override closer to the LHS type.
4150 if (!IsBase && best_candidate.IsVirtual) {
4151 if (TypeManager.IsOverride (best_candidate))
4152 throw new InternalErrorException (
4153 "Should not happen. An 'override' method took part in overload resolution: " + best_candidate);
4155 if (candidate_overrides != null)
4156 foreach (MethodBase candidate in candidate_overrides) {
4157 if (IsOverride (candidate, best_candidate))
4158 best_candidate = candidate;
4162 // We can stop here when probing is on
4163 if (ec.IsInProbingMode)
4167 // And now check if the arguments are all
4168 // compatible, perform conversions if
4169 // necessary etc. and return if everything is
4172 if (!VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate,
4173 method_params, null, may_fail, loc))
4176 if (best_candidate == null)
4179 MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
4181 if (the_method.IsGenericMethodDefinition &&
4182 !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
4186 IMethodData data = TypeManager.GetMethod (the_method);
4188 data.SetMemberIsUsed ();
4193 public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
4196 if (!args.Resolve (ec))
4199 Type[] atypes = args.Arguments;
4201 int first_count = 0;
4202 MethodInfo first = null;
4204 ArrayList list = new ArrayList ();
4205 foreach (MethodBase mb in Methods) {
4206 MethodInfo mi = mb as MethodInfo;
4207 if ((mi == null) || !mb.IsGenericMethod)
4210 Type[] gen_params = mb.GetGenericArguments ();
4212 if (first == null) {
4214 first_count = gen_params.Length;
4217 if (gen_params.Length != atypes.Length)
4220 mi = mi.MakeGenericMethod (atypes);
4224 // MS implementation throws NotSupportedException for GetParameters
4225 // on unbaked generic method
4226 Parameters p = TypeManager.GetParameterData (mi) as Parameters;
4229 p.InflateTypes (gen_params, atypes);
4230 TypeManager.RegisterMethod (mi, p);
4235 if (list.Count > 0) {
4236 this.Methods = (MethodBase []) list.ToArray (typeof (MethodBase));
4237 has_type_arguments = true;
4241 if (first != null) {
4242 Report.SymbolRelatedToPreviousError (first);
4244 305, loc, "Using the generic method `{0}' requires `{1}' type arguments",
4245 TypeManager.CSharpSignature (first), first_count.ToString ());
4248 308, loc, "The non-generic method `{0}' " +
4249 "cannot be used with type arguments", Name);
4253 throw new NotImplementedException ();
4257 public bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
4258 int arg_count, MethodBase method,
4259 bool chose_params_expanded,
4260 Type delegate_type, bool may_fail, Location loc)
4262 ParameterData pd = TypeManager.GetParameterData (method);
4263 int param_count = GetApplicableParametersCount (method, pd);
4268 for (j = 0; j < param_count; j++) {
4269 Type parameter_type = pd.ParameterType (j);
4270 Parameter.Modifier pm = pd.ParameterModifier (j);
4272 if (pm == Parameter.Modifier.ARGLIST) {
4273 a = (Argument) Arguments [a_idx];
4274 if (!(a.Expr is Arglist))
4280 int params_arg_count = 1;
4281 if (pm == Parameter.Modifier.PARAMS) {
4282 pm = Parameter.Modifier.NONE;
4283 params_arg_count = arg_count - param_count + 1;
4284 if (chose_params_expanded)
4285 parameter_type = TypeManager.GetElementType (parameter_type);
4288 while (params_arg_count > 0) {
4289 a = (Argument) Arguments [a_idx];
4290 if (pm != a.Modifier)
4293 if (!TypeManager.IsEqual (a.Type, parameter_type)) {
4294 if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF)
4297 Expression conv = Convert.ImplicitConversion (ec, a.Expr, parameter_type, loc);
4301 // Update the argument with the implicit conversion
4309 if (params_arg_count > 0)
4312 if (parameter_type.IsPointer && !ec.InUnsafe) {
4319 if (a_idx == arg_count)
4323 Error_InvalidArguments (ec, loc, a_idx, method, delegate_type, a, pd);
4329 /// Fully resolved expression that evaluates to a Field
4331 public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable {
4332 public readonly FieldInfo FieldInfo;
4333 VariableInfo variable_info;
4335 LocalTemporary temp;
4337 bool in_initializer;
4339 public FieldExpr (FieldInfo fi, Location l, bool in_initializer):
4342 this.in_initializer = in_initializer;
4345 public FieldExpr (FieldInfo fi, Location l)
4348 eclass = ExprClass.Variable;
4349 type = TypeManager.TypeToCoreType (fi.FieldType);
4353 public override string Name {
4355 return FieldInfo.Name;
4359 public override bool IsInstance {
4361 return !FieldInfo.IsStatic;
4365 public override bool IsStatic {
4367 return FieldInfo.IsStatic;
4371 public override Type DeclaringType {
4373 return FieldInfo.DeclaringType;
4377 public override string GetSignatureForError ()
4379 return TypeManager.GetFullNameSignature (FieldInfo);
4382 public VariableInfo VariableInfo {
4384 return variable_info;
4388 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
4389 SimpleName original)
4391 FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo);
4393 Type t = fi.FieldType;
4395 if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) {
4396 IConstant ic = TypeManager.GetConstant (fi);
4399 ic = new ExternalConstant (fi);
4401 ic = ExternalConstant.CreateDecimal (fi);
4403 return base.ResolveMemberAccess (ec, left, loc, original);
4406 TypeManager.RegisterConstant (fi, ic);
4409 bool left_is_type = left is TypeExpr;
4410 if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) {
4411 Report.SymbolRelatedToPreviousError (FieldInfo);
4412 error176 (loc, TypeManager.GetFullNameSignature (FieldInfo));
4416 if (ic.ResolveValue ()) {
4417 if (!ec.IsInObsoleteScope)
4418 ic.CheckObsoleteness (loc);
4421 return ic.CreateConstantReference (loc);
4424 if (t.IsPointer && !ec.InUnsafe) {
4428 return base.ResolveMemberAccess (ec, left, loc, original);
4431 override public Expression DoResolve (EmitContext ec)
4433 return DoResolve (ec, false, false);
4436 Expression DoResolve (EmitContext ec, bool lvalue_instance, bool out_access)
4438 if (!FieldInfo.IsStatic){
4439 if (InstanceExpression == null){
4441 // This can happen when referencing an instance field using
4442 // a fully qualified type expression: TypeName.InstanceField = xxx
4444 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
4448 // Resolve the field's instance expression while flow analysis is turned
4449 // off: when accessing a field "a.b", we must check whether the field
4450 // "a.b" is initialized, not whether the whole struct "a" is initialized.
4452 if (lvalue_instance) {
4453 using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) {
4454 Expression right_side =
4455 out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
4456 InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc);
4459 ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis;
4460 InstanceExpression = InstanceExpression.Resolve (ec, rf);
4463 if (InstanceExpression == null)
4466 InstanceExpression.CheckMarshalByRefAccess ();
4469 if (!in_initializer && !ec.IsInFieldInitializer) {
4470 ObsoleteAttribute oa;
4471 FieldBase f = TypeManager.GetField (FieldInfo);
4473 if (!ec.IsInObsoleteScope)
4474 f.CheckObsoleteness (loc);
4476 // To be sure that type is external because we do not register generated fields
4477 } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
4478 oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
4480 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
4484 AnonymousContainer am = ec.CurrentAnonymousMethod;
4486 if (!FieldInfo.IsStatic){
4487 if (!am.IsIterator && (ec.TypeContainer is Struct)){
4488 Report.Error (1673, loc,
4489 "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",
4496 IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo);
4498 if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) {
4499 Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
4502 if (!(InstanceExpression is LocalVariableReference) &&
4503 !(InstanceExpression is This)) {
4504 Report.SymbolRelatedToPreviousError (FieldInfo);
4505 Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
4506 TypeManager.GetFullNameSignature (FieldInfo));
4509 return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
4512 // If the instance expression is a local variable or parameter.
4513 IVariable var = InstanceExpression as IVariable;
4514 if ((var == null) || (var.VariableInfo == null))
4517 VariableInfo vi = var.VariableInfo;
4518 if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc))
4521 variable_info = vi.GetSubStruct (FieldInfo.Name);
4525 static readonly int [] codes = {
4526 191, // instance, write access
4527 192, // instance, out access
4528 198, // static, write access
4529 199, // static, out access
4530 1648, // member of value instance, write access
4531 1649, // member of value instance, out access
4532 1650, // member of value static, write access
4533 1651 // member of value static, out access
4536 static readonly string [] msgs = {
4537 /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
4538 /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
4539 /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
4540 /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
4541 /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
4542 /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
4543 /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
4544 /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
4547 // The return value is always null. Returning a value simplifies calling code.
4548 Expression Report_AssignToReadonly (Expression right_side)
4551 if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess)
4555 if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
4557 Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
4562 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
4564 IVariable var = InstanceExpression as IVariable;
4565 if ((var != null) && (var.VariableInfo != null))
4566 var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name);
4568 bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType;
4569 bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess;
4571 Expression e = DoResolve (ec, lvalue_instance, out_access);
4576 FieldBase fb = TypeManager.GetField (FieldInfo);
4580 if (FieldInfo.IsInitOnly) {
4581 // InitOnly fields can only be assigned in constructors or initializers
4582 if (!ec.IsInFieldInitializer && !ec.IsConstructor)
4583 return Report_AssignToReadonly (right_side);
4585 if (ec.IsConstructor) {
4586 Type ctype = ec.TypeContainer.CurrentType;
4588 ctype = ec.ContainerType;
4590 // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
4591 if (!TypeManager.IsEqual (ctype, FieldInfo.DeclaringType))
4592 return Report_AssignToReadonly (right_side);
4593 // static InitOnly fields cannot be assigned-to in an instance constructor
4594 if (IsStatic && !ec.IsStatic)
4595 return Report_AssignToReadonly (right_side);
4596 // instance constructors can't modify InitOnly fields of other instances of the same type
4597 if (!IsStatic && !(InstanceExpression is This))
4598 return Report_AssignToReadonly (right_side);
4602 if (right_side == EmptyExpression.OutAccess &&
4603 !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
4604 Report.SymbolRelatedToPreviousError (DeclaringType);
4605 Report.Warning (197, 1, loc,
4606 "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class",
4607 GetSignatureForError ());
4613 public override void CheckMarshalByRefAccess ()
4615 if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) {
4616 Report.SymbolRelatedToPreviousError (DeclaringType);
4617 Report.Warning (1690, 1, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
4618 GetSignatureForError ());
4622 public bool VerifyFixed ()
4624 IVariable variable = InstanceExpression as IVariable;
4625 // A variable of the form V.I is fixed when V is a fixed variable of a struct type.
4626 // We defer the InstanceExpression check after the variable check to avoid a
4627 // separate null check on InstanceExpression.
4628 return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed ();
4631 public override int GetHashCode ()
4633 return FieldInfo.GetHashCode ();
4636 public override bool Equals (object obj)
4638 FieldExpr fe = obj as FieldExpr;
4642 if (FieldInfo != fe.FieldInfo)
4645 if (InstanceExpression == null || fe.InstanceExpression == null)
4648 return InstanceExpression.Equals (fe.InstanceExpression);
4651 public void Emit (EmitContext ec, bool leave_copy)
4653 ILGenerator ig = ec.ig;
4654 bool is_volatile = false;
4656 FieldBase f = TypeManager.GetField (FieldInfo);
4658 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
4661 f.SetMemberIsUsed ();
4664 if (FieldInfo.IsStatic){
4666 ig.Emit (OpCodes.Volatile);
4668 ig.Emit (OpCodes.Ldsfld, FieldInfo);
4671 EmitInstance (ec, false);
4673 IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
4675 ig.Emit (OpCodes.Ldflda, FieldInfo);
4676 ig.Emit (OpCodes.Ldflda, ff.Element);
4679 ig.Emit (OpCodes.Volatile);
4681 ig.Emit (OpCodes.Ldfld, FieldInfo);
4686 ec.ig.Emit (OpCodes.Dup);
4687 if (!FieldInfo.IsStatic) {
4688 temp = new LocalTemporary (this.Type);
4694 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
4696 FieldAttributes fa = FieldInfo.Attributes;
4697 bool is_static = (fa & FieldAttributes.Static) != 0;
4698 bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
4699 ILGenerator ig = ec.ig;
4701 if (is_readonly && !ec.IsConstructor){
4702 Report_AssignToReadonly (source);
4707 // String concatenation creates a new string instance
4709 prepared = prepare_for_load && !(source is StringConcat);
4710 EmitInstance (ec, prepared);
4714 ec.ig.Emit (OpCodes.Dup);
4715 if (!FieldInfo.IsStatic) {
4716 temp = new LocalTemporary (this.Type);
4721 FieldBase f = TypeManager.GetField (FieldInfo);
4723 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
4724 ig.Emit (OpCodes.Volatile);
4730 ig.Emit (OpCodes.Stsfld, FieldInfo);
4732 ig.Emit (OpCodes.Stfld, FieldInfo);
4740 public override void Emit (EmitContext ec)
4745 public void AddressOf (EmitContext ec, AddressOp mode)
4747 ILGenerator ig = ec.ig;
4749 FieldBase f = TypeManager.GetField (FieldInfo);
4751 if ((f.ModFlags & Modifiers.VOLATILE) != 0){
4752 Report.Warning (420, 1, loc, "`{0}': A volatile field references will not be treated as volatile",
4753 f.GetSignatureForError ());
4756 if ((mode & AddressOp.Store) != 0)
4758 if ((mode & AddressOp.Load) != 0)
4759 f.SetMemberIsUsed ();
4763 // Handle initonly fields specially: make a copy and then
4764 // get the address of the copy.
4767 if (FieldInfo.IsInitOnly){
4769 if (ec.IsConstructor){
4770 if (FieldInfo.IsStatic){
4782 local = ig.DeclareLocal (type);
4783 ig.Emit (OpCodes.Stloc, local);
4784 ig.Emit (OpCodes.Ldloca, local);
4789 if (FieldInfo.IsStatic){
4790 ig.Emit (OpCodes.Ldsflda, FieldInfo);
4793 EmitInstance (ec, false);
4794 ig.Emit (OpCodes.Ldflda, FieldInfo);
4800 // A FieldExpr whose address can not be taken
4802 public class FieldExprNoAddress : FieldExpr, IMemoryLocation {
4803 public FieldExprNoAddress (FieldInfo fi, Location loc) : base (fi, loc)
4807 public new void AddressOf (EmitContext ec, AddressOp mode)
4809 Report.Error (-215, "Report this: Taking the address of a remapped parameter not supported");
4814 /// Expression that evaluates to a Property. The Assign class
4815 /// might set the `Value' expression if we are in an assignment.
4817 /// This is not an LValue because we need to re-write the expression, we
4818 /// can not take data from the stack and store it.
4820 public class PropertyExpr : MemberExpr, IAssignMethod {
4821 public readonly PropertyInfo PropertyInfo;
4824 // This is set externally by the `BaseAccess' class
4827 MethodInfo getter, setter;
4832 LocalTemporary temp;
4835 public PropertyExpr (Type containerType, PropertyInfo pi, Location l)
4838 eclass = ExprClass.PropertyAccess;
4842 type = TypeManager.TypeToCoreType (pi.PropertyType);
4844 ResolveAccessors (containerType);
4847 public override string Name {
4849 return PropertyInfo.Name;
4853 public override bool IsInstance {
4859 public override bool IsStatic {
4865 public override Type DeclaringType {
4867 return PropertyInfo.DeclaringType;
4871 public override string GetSignatureForError ()
4873 return TypeManager.GetFullNameSignature (PropertyInfo);
4876 void FindAccessors (Type invocation_type)
4878 const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic |
4879 BindingFlags.Static | BindingFlags.Instance |
4880 BindingFlags.DeclaredOnly;
4882 Type current = PropertyInfo.DeclaringType;
4883 for (; current != null; current = current.BaseType) {
4884 MemberInfo[] group = TypeManager.MemberLookup (
4885 invocation_type, invocation_type, current,
4886 MemberTypes.Property, flags, PropertyInfo.Name, null);
4891 if (group.Length != 1)
4892 // Oooops, can this ever happen ?
4895 PropertyInfo pi = (PropertyInfo) group [0];
4898 getter = pi.GetGetMethod (true);
4901 setter = pi.GetSetMethod (true);
4903 MethodInfo accessor = getter != null ? getter : setter;
4905 if (!accessor.IsVirtual)
4911 // We also perform the permission checking here, as the PropertyInfo does not
4912 // hold the information for the accessibility of its setter/getter
4914 // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor
4915 void ResolveAccessors (Type containerType)
4917 FindAccessors (containerType);
4919 if (getter != null) {
4920 MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter);
4921 IMethodData md = TypeManager.GetMethod (the_getter);
4923 md.SetMemberIsUsed ();
4925 is_static = getter.IsStatic;
4928 if (setter != null) {
4929 MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter);
4930 IMethodData md = TypeManager.GetMethod (the_setter);
4932 md.SetMemberIsUsed ();
4934 is_static = setter.IsStatic;
4938 bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check)
4941 InstanceExpression = null;
4945 if (InstanceExpression == null) {
4946 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
4950 InstanceExpression = InstanceExpression.DoResolve (ec);
4951 if (lvalue_instance && InstanceExpression != null)
4952 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc);
4954 if (InstanceExpression == null)
4957 InstanceExpression.CheckMarshalByRefAccess ();
4959 if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
4960 !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) &&
4961 !TypeManager.IsNestedChildOf (ec.ContainerType, InstanceExpression.Type) &&
4962 !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.ContainerType)) {
4963 Report.SymbolRelatedToPreviousError (PropertyInfo);
4964 Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType);
4971 void Error_PropertyNotFound (MethodInfo mi, bool getter)
4973 // TODO: correctly we should compare arguments but it will lead to bigger changes
4974 if (mi is MethodBuilder) {
4975 Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name);
4979 StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType));
4981 ParameterData iparams = TypeManager.GetParameterData (mi);
4982 sig.Append (getter ? "get_" : "set_");
4984 sig.Append (iparams.GetSignatureForError ());
4986 Report.SymbolRelatedToPreviousError (mi);
4987 Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
4988 Name, sig.ToString ());
4991 public bool IsAccessibleFrom (Type invocation_type, bool lvalue)
4994 MethodInfo accessor = lvalue ? setter : getter;
4995 if (accessor == null && lvalue)
4997 return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy);
5000 override public Expression DoResolve (EmitContext ec)
5005 if (getter != null){
5006 if (TypeManager.GetParameterData (getter).Count != 0){
5007 Error_PropertyNotFound (getter, true);
5012 if (getter == null){
5014 // The following condition happens if the PropertyExpr was
5015 // created, but is invalid (ie, the property is inaccessible),
5016 // and we did not want to embed the knowledge about this in
5017 // the caller routine. This only avoids double error reporting.
5022 if (InstanceExpression != EmptyExpression.Null) {
5023 Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
5024 TypeManager.GetFullNameSignature (PropertyInfo));
5029 bool must_do_cs1540_check = false;
5030 if (getter != null &&
5031 !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) {
5032 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod;
5033 if (pm != null && pm.HasCustomAccessModifier) {
5034 Report.SymbolRelatedToPreviousError (pm);
5035 Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
5036 TypeManager.CSharpSignature (getter));
5039 Report.SymbolRelatedToPreviousError (getter);
5040 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter));
5045 if (!InstanceResolve (ec, false, must_do_cs1540_check))
5049 // Only base will allow this invocation to happen.
5051 if (IsBase && getter.IsAbstract) {
5052 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
5056 if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){
5066 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5068 if (right_side == EmptyExpression.OutAccess) {
5069 Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
5070 GetSignatureForError ());
5074 if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
5075 Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
5076 GetSignatureForError ());
5080 if (setter == null){
5082 // The following condition happens if the PropertyExpr was
5083 // created, but is invalid (ie, the property is inaccessible),
5084 // and we did not want to embed the knowledge about this in
5085 // the caller routine. This only avoids double error reporting.
5089 Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
5090 GetSignatureForError ());
5094 if (TypeManager.GetParameterData (setter).Count != 1){
5095 Error_PropertyNotFound (setter, false);
5099 bool must_do_cs1540_check;
5100 if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) {
5101 PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod;
5102 if (pm != null && pm.HasCustomAccessModifier) {
5103 Report.SymbolRelatedToPreviousError (pm);
5104 Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
5105 TypeManager.CSharpSignature (setter));
5108 Report.SymbolRelatedToPreviousError (setter);
5109 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter));
5114 if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check))
5118 // Only base will allow this invocation to happen.
5120 if (IsBase && setter.IsAbstract){
5121 Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo));
5128 public override void Emit (EmitContext ec)
5133 public void Emit (EmitContext ec, bool leave_copy)
5136 // Special case: length of single dimension array property is turned into ldlen
5138 if ((getter == TypeManager.system_int_array_get_length) ||
5139 (getter == TypeManager.int_array_get_length)){
5140 Type iet = InstanceExpression.Type;
5143 // System.Array.Length can be called, but the Type does not
5144 // support invoking GetArrayRank, so test for that case first
5146 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) {
5148 EmitInstance (ec, false);
5149 ec.ig.Emit (OpCodes.Ldlen);
5150 ec.ig.Emit (OpCodes.Conv_I4);
5155 Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
5158 ec.ig.Emit (OpCodes.Dup);
5160 temp = new LocalTemporary (this.Type);
5167 // Implements the IAssignMethod interface for assignments
5169 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5171 Expression my_source = source;
5173 if (prepare_for_load) {
5174 if (source is StringConcat)
5175 EmitInstance (ec, false);
5183 ec.ig.Emit (OpCodes.Dup);
5185 temp = new LocalTemporary (this.Type);
5189 } else if (leave_copy) {
5191 temp = new LocalTemporary (this.Type);
5196 ArrayList args = new ArrayList (1);
5197 args.Add (new Argument (my_source, Argument.AType.Expression));
5199 Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared);
5209 /// Fully resolved expression that evaluates to an Event
5211 public class EventExpr : MemberExpr {
5212 public readonly EventInfo EventInfo;
5216 MethodInfo add_accessor, remove_accessor;
5218 public EventExpr (EventInfo ei, Location loc)
5222 eclass = ExprClass.EventAccess;
5224 add_accessor = TypeManager.GetAddMethod (ei);
5225 remove_accessor = TypeManager.GetRemoveMethod (ei);
5226 if (add_accessor.IsStatic || remove_accessor.IsStatic)
5229 if (EventInfo is MyEventBuilder){
5230 MyEventBuilder eb = (MyEventBuilder) EventInfo;
5231 type = eb.EventType;
5234 type = EventInfo.EventHandlerType;
5237 public override string Name {
5239 return EventInfo.Name;
5243 public override bool IsInstance {
5249 public override bool IsStatic {
5255 public override Type DeclaringType {
5257 return EventInfo.DeclaringType;
5261 public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
5262 SimpleName original)
5265 // If the event is local to this class, we transform ourselves into a FieldExpr
5268 if (EventInfo.DeclaringType == ec.ContainerType ||
5269 TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) {
5270 EventField mi = TypeManager.GetEventField (EventInfo);
5273 if (!ec.IsInObsoleteScope)
5274 mi.CheckObsoleteness (loc);
5276 FieldExpr ml = new FieldExpr (mi.FieldBuilder, loc);
5278 InstanceExpression = null;
5280 return ml.ResolveMemberAccess (ec, left, loc, original);
5284 return base.ResolveMemberAccess (ec, left, loc, original);
5288 bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check)
5291 InstanceExpression = null;
5295 if (InstanceExpression == null) {
5296 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
5300 InstanceExpression = InstanceExpression.DoResolve (ec);
5301 if (InstanceExpression == null)
5304 if (IsBase && add_accessor.IsAbstract) {
5305 Error_CannotCallAbstractBase(TypeManager.CSharpSignature(add_accessor));
5310 // This is using the same mechanism as the CS1540 check in PropertyExpr.
5311 // However, in the Event case, we reported a CS0122 instead.
5313 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
5314 InstanceExpression.Type != ec.ContainerType &&
5315 ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) {
5316 Report.SymbolRelatedToPreviousError (EventInfo);
5317 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
5324 public bool IsAccessibleFrom (Type invocation_type)
5327 return IsAccessorAccessible (invocation_type, add_accessor, out dummy) &&
5328 IsAccessorAccessible (invocation_type, remove_accessor, out dummy);
5331 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
5333 return DoResolve (ec);
5336 public override Expression DoResolve (EmitContext ec)
5338 bool must_do_cs1540_check;
5339 if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) &&
5340 IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) {
5341 Report.SymbolRelatedToPreviousError (EventInfo);
5342 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo));
5346 if (!InstanceResolve (ec, must_do_cs1540_check))
5352 public override void Emit (EmitContext ec)
5354 if (InstanceExpression is This)
5355 Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ());
5357 Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+
5358 "(except on the defining type)", Name);
5361 public override string GetSignatureForError ()
5363 return TypeManager.CSharpSignature (EventInfo);
5366 public void EmitAddOrRemove (EmitContext ec, Expression source)
5368 BinaryDelegate source_del = source as BinaryDelegate;
5369 if (source_del == null) {
5373 Expression handler = source_del.Right;
5375 Argument arg = new Argument (handler, Argument.AType.Expression);
5376 ArrayList args = new ArrayList ();
5380 if (source_del.IsAddition)
5381 Invocation.EmitCall (
5382 ec, IsBase, InstanceExpression, add_accessor, args, loc);
5384 Invocation.EmitCall (
5385 ec, IsBase, InstanceExpression, remove_accessor, args, loc);
5389 public class TemporaryVariable : Expression, IMemoryLocation
5394 public TemporaryVariable (Type type, Location loc)
5398 eclass = ExprClass.Value;
5401 public override Expression DoResolve (EmitContext ec)
5406 TypeExpr te = new TypeExpression (type, loc);
5407 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
5408 if (!li.Resolve (ec))
5411 if (ec.MustCaptureVariable (li)) {
5412 ScopeInfo scope = li.Block.CreateScopeInfo ();
5413 var = scope.AddLocal (li);
5420 public Variable Variable {
5421 get { return var != null ? var : li.Variable; }
5424 public override void Emit (EmitContext ec)
5426 Variable.EmitInstance (ec);
5430 public void EmitLoadAddress (EmitContext ec)
5432 Variable.EmitInstance (ec);
5433 Variable.EmitAddressOf (ec);
5436 public void Store (EmitContext ec, Expression right_side)
5438 Variable.EmitInstance (ec);
5439 right_side.Emit (ec);
5440 Variable.EmitAssign (ec);
5443 public void EmitThis (EmitContext ec)
5445 Variable.EmitInstance (ec);
5448 public void EmitStore (EmitContext ec)
5450 Variable.EmitAssign (ec);
5453 public void AddressOf (EmitContext ec, AddressOp mode)
5455 EmitLoadAddress (ec);
5460 /// Handles `var' contextual keyword; var becomes a keyword only
5461 /// if no type called var exists in a variable scope
5463 public class VarExpr : SimpleName
5465 // Used for error reporting only
5466 ArrayList initializer;
5468 public VarExpr (string name, Location loc)
5473 public ArrayList VariableInitializer {
5475 this.initializer = value;
5479 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
5482 throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
5484 type = right_side.Type;
5485 if (type == TypeManager.null_type || type == TypeManager.void_type || type == TypeManager.anonymous_method_type) {
5486 Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
5487 right_side.GetSignatureForError ());
5491 eclass = ExprClass.Variable;
5495 protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec)
5497 if (ec is FieldBase) {
5498 Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
5502 base.Error_TypeOrNamespaceNotFound (ec);
5505 public override TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent)
5507 TypeExpr te = base.ResolveAsContextualType (rc, true);
5511 if (initializer == null)
5514 // TODO: refactor, the error is reported too many times
5515 if (initializer.Count > 1) {
5516 Location loc = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [1]).Location;
5517 Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
5521 Expression variable_initializer = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [0]).expression_or_array_initializer;
5522 if (variable_initializer == null) {
5523 Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");