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 // Copyright 2001, 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2008 Novell, Inc.
14 using System.Collections.Generic;
15 using System.Diagnostics;
16 using System.Reflection;
17 using System.Reflection.Emit;
19 using SLE = System.Linq.Expressions;
22 namespace Mono.CSharp {
25 /// The ExprClass class contains the is used to pass the
26 /// classification of an expression (value, variable, namespace,
27 /// type, method group, property access, event access, indexer access,
30 public enum ExprClass : byte {
46 /// This is used to tell Resolve in which types of expressions we're
50 public enum ResolveFlags {
51 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
54 // Returns a type expression.
57 // Returns a method group.
60 TypeParameter = 1 << 3,
62 // Mask of all the expression class flags.
63 MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter,
65 // Set if this is resolving the first part of a MemberAccess.
66 Intermediate = 1 << 11,
70 // This is just as a hint to AddressOf of what will be done with the
73 public enum AddressOp {
80 /// This interface is implemented by variables
82 public interface IMemoryLocation {
84 /// The AddressOf method should generate code that loads
85 /// the address of the object and leaves it on the stack.
87 /// The `mode' argument is used to notify the expression
88 /// of whether this will be used to read from the address or
89 /// write to the address.
91 /// This is just a hint that can be used to provide good error
92 /// reporting, and should have no other side effects.
94 void AddressOf (EmitContext ec, AddressOp mode);
98 // An expressions resolved as a direct variable reference
100 public interface IVariableReference : IFixedExpression
102 bool IsHoisted { get; }
104 VariableInfo VariableInfo { get; }
106 void SetHasAddressTaken ();
110 // Implemented by an expression which could be or is always
113 public interface IFixedExpression
115 bool IsFixed { get; }
119 /// Base class for expressions
121 public abstract class Expression {
122 public ExprClass eclass;
123 protected TypeSpec type;
124 protected Location loc;
126 public TypeSpec Type {
128 set { type = value; }
131 public virtual Location Location {
135 // Not nice but we have broken hierarchy.
136 public virtual void CheckMarshalByRefAccess (ResolveContext ec)
140 public virtual string GetSignatureForError ()
142 return type.GetDefinition ().GetSignatureForError ();
145 public static bool IsMemberAccessible (TypeSpec invocation_type, MemberSpec mi, out bool must_do_cs1540_check)
147 var ma = mi.Modifiers & Modifiers.AccessibilityMask;
149 must_do_cs1540_check = false; // by default we do not check for this
151 if (ma == Modifiers.PUBLIC)
155 // If only accessible to the current class or children
157 if (ma == Modifiers.PRIVATE)
158 return invocation_type.MemberDefinition == mi.DeclaringType.MemberDefinition ||
159 TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);
161 if ((ma & Modifiers.INTERNAL) != 0) {
162 var b = TypeManager.IsThisOrFriendAssembly (invocation_type == InternalType.FakeInternalType ?
163 CodeGen.Assembly.Builder : invocation_type.Assembly, mi.DeclaringType.Assembly);
164 if (b || ma == Modifiers.INTERNAL)
168 // Family and FamANDAssem require that we derive.
169 // FamORAssem requires that we derive if in different assemblies.
170 if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))
173 if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))
174 must_do_cs1540_check = true;
179 public virtual bool IsNull {
186 /// Performs semantic analysis on the Expression
190 /// The Resolve method is invoked to perform the semantic analysis
193 /// The return value is an expression (it can be the
194 /// same expression in some cases) or a new
195 /// expression that better represents this node.
197 /// For example, optimizations of Unary (LiteralInt)
198 /// would return a new LiteralInt with a negated
201 /// If there is an error during semantic analysis,
202 /// then an error should be reported (using Report)
203 /// and a null value should be returned.
205 /// There are two side effects expected from calling
206 /// Resolve(): the the field variable "eclass" should
207 /// be set to any value of the enumeration
208 /// `ExprClass' and the type variable should be set
209 /// to a valid type (this is the type of the
212 protected abstract Expression DoResolve (ResolveContext rc);
214 public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side)
220 // This is used if the expression should be resolved as a type or namespace name.
221 // the default implementation fails.
223 public virtual FullNamedExpression ResolveAsTypeStep (IMemberContext rc, bool silent)
226 ResolveContext ec = new ResolveContext (rc);
227 Expression e = Resolve (ec);
229 e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc);
236 // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
237 // same name exists or as a keyword when no type was found
239 public virtual TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
241 return ResolveAsTypeTerminal (rc, silent);
245 // This is used to resolve the expression as a type, a null
246 // value will be returned if the expression is not a type
249 public virtual TypeExpr ResolveAsTypeTerminal (IMemberContext ec , bool silent)
251 int errors = ec.Compiler.Report.Errors;
253 FullNamedExpression fne = ResolveAsTypeStep (ec, silent);
258 TypeExpr te = fne as TypeExpr;
260 if (!silent && errors == ec.Compiler.Report.Errors)
261 fne.Error_UnexpectedKind (ec.Compiler.Report, null, "type", loc);
265 if (!te.CheckAccessLevel (ec)) {
266 ec.Compiler.Report.SymbolRelatedToPreviousError (te.Type);
267 ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type), ec.Compiler.Report);
273 // Obsolete checks cannot be done when resolving base context as they
274 // require type dependecies to be set but we are just resolving them
276 if (!silent && !(ec is TypeContainer.BaseContext)) {
277 ObsoleteAttribute obsolete_attr = te.Type.GetAttributeObsolete ();
278 if (obsolete_attr != null && !ec.IsObsolete) {
279 AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, ec.Compiler.Report);
286 public static void ErrorIsInaccesible (Location loc, string name, Report Report)
288 Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);
291 protected static void Error_CannotAccessProtected (ResolveContext ec, Location loc, MemberSpec m, TypeSpec qualifier, TypeSpec container)
293 ec.Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'."
294 + " The qualifier must be of type `{2}' or derived from it",
295 m.GetSignatureForError (),
296 TypeManager.CSharpName (qualifier),
297 TypeManager.CSharpName (container));
301 public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name)
303 rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name);
306 public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name)
308 rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null",
309 name, TypeManager.CSharpName (type));
312 public static void Error_InvalidExpressionStatement (Report Report, Location loc)
314 Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " +
315 "expressions can be used as a statement");
318 public void Error_InvalidExpressionStatement (BlockContext ec)
320 Error_InvalidExpressionStatement (ec.Report, loc);
323 public static void Error_VoidInvalidInTheContext (Location loc, Report Report)
325 Report.Error (1547, loc, "Keyword `void' cannot be used in this context");
328 public virtual void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
330 Error_ValueCannotBeConvertedCore (ec, loc, target, expl);
333 protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl)
335 // The error was already reported as CS1660
336 if (type == InternalType.AnonymousMethod)
340 if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) {
341 string sig1 = type.DeclaringMethod == null ?
342 TypeManager.CSharpName (type.DeclaringType) :
343 TypeManager.CSharpSignature (type.DeclaringMethod);
344 string sig2 = target.DeclaringMethod == null ?
345 TypeManager.CSharpName (target.DeclaringType) :
346 TypeManager.CSharpSignature (target.DeclaringMethod);
347 ec.Report.ExtraInformation (loc,
349 "The generic parameter `{0}' of `{1}' cannot be converted to the generic parameter `{0}' of `{2}' (in the previous ",
350 Type.Name, sig1, sig2));
351 } else if (Type.MetaInfo.FullName == target.MetaInfo.FullName) {
352 ec.Report.ExtraInformation (loc,
354 "The type `{0}' has two conflicting definitions, one comes from `{1}' and the other from `{2}' (in the previous ",
355 Type.MetaInfo.FullName, Type.Assembly.FullName, target.Assembly.FullName));
359 ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
360 TypeManager.CSharpName (type), TypeManager.CSharpName (target));
364 ec.Report.DisableReporting ();
365 bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null;
366 ec.Report.EnableReporting ();
369 ec.Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " +
370 "An explicit conversion exists (are you missing a cast?)",
371 TypeManager.CSharpName (Type), TypeManager.CSharpName (target));
375 ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
376 type.GetSignatureForError (), target.GetSignatureForError ());
379 public virtual void Error_VariableIsUsedBeforeItIsDeclared (Report Report, string name)
381 Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", name);
384 public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity)
386 // Better message for possible generic expressions
387 if (member != null && (member.Kind & MemberKind.GenericMask) != 0) {
388 report.SymbolRelatedToPreviousError (member);
389 if (member is TypeSpec)
390 member = ((TypeSpec) member).GetDefinition ();
392 member = ((MethodSpec) member).GetGenericMethodDefinition ();
394 string name = member.Kind == MemberKind.Method ? "method" : "type";
395 if (member.IsGeneric) {
396 report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)",
397 name, member.GetSignatureForError (), member.Arity.ToString ());
399 report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments",
400 name, member.GetSignatureForError ());
403 report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments",
404 ExprClassName, GetSignatureForError ());
408 protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name)
410 Error_TypeDoesNotContainDefinition (ec, loc, type, name);
413 public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name)
415 ec.Report.SymbolRelatedToPreviousError (type);
416 ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
417 TypeManager.CSharpName (type), name);
420 protected static void Error_ValueAssignment (ResolveContext ec, Location loc)
422 ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer");
425 ResolveFlags ExprClassToResolveFlags {
429 case ExprClass.Namespace:
430 return ResolveFlags.Type;
432 case ExprClass.MethodGroup:
433 return ResolveFlags.MethodGroup;
435 case ExprClass.TypeParameter:
436 return ResolveFlags.TypeParameter;
438 case ExprClass.Value:
439 case ExprClass.Variable:
440 case ExprClass.PropertyAccess:
441 case ExprClass.EventAccess:
442 case ExprClass.IndexerAccess:
443 return ResolveFlags.VariableOrValue;
446 throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve");
452 /// Resolves an expression and performs semantic analysis on it.
456 /// Currently Resolve wraps DoResolve to perform sanity
457 /// checking and assertion checking on what we expect from Resolve.
459 public Expression Resolve (ResolveContext ec, ResolveFlags flags)
461 if (eclass != ExprClass.Unresolved)
465 if (this is SimpleName) {
466 e = ((SimpleName) this).DoResolve (ec, (flags & ResolveFlags.Intermediate) != 0);
474 if ((flags & e.ExprClassToResolveFlags) == 0) {
475 e.Error_UnexpectedKind (ec, flags, loc);
480 throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ());
486 /// Resolves an expression and performs semantic analysis on it.
488 public Expression Resolve (ResolveContext rc)
490 return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
494 /// Resolves an expression for LValue assignment
498 /// Currently ResolveLValue wraps DoResolveLValue to perform sanity
499 /// checking and assertion checking on what we expect from Resolve
501 public Expression ResolveLValue (ResolveContext ec, Expression right_side)
503 int errors = ec.Report.Errors;
504 bool out_access = right_side == EmptyExpression.OutAccess.Instance;
506 Expression e = DoResolveLValue (ec, right_side);
508 if (e != null && out_access && !(e is IMemoryLocation)) {
509 // FIXME: There's no problem with correctness, the 'Expr = null' handles that.
510 // Enabling this 'throw' will "only" result in deleting useless code elsewhere,
512 //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " +
513 // e.GetType () + " " + e.GetSignatureForError ());
518 if (errors == ec.Report.Errors) {
520 ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable");
522 Error_ValueAssignment (ec, loc);
527 if (e.eclass == ExprClass.Unresolved)
528 throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve");
530 if ((e.type == null) && !(e is GenericTypeExpr))
531 throw new Exception ("Expression " + e + " did not set its type after Resolve");
536 public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
538 Attribute.Error_AttributeArgumentNotValid (rc, loc);
542 /// Emits the code for the expression
546 /// The Emit method is invoked to generate the code
547 /// for the expression.
549 public abstract void Emit (EmitContext ec);
552 // Emit code to branch to @target if this expression is equivalent to @on_true.
553 // The default implementation is to emit the value, and then emit a brtrue or brfalse.
554 // Subclasses can provide more efficient implementations, but those MUST be equivalent,
555 // including the use of conditional branches. Note also that a branch MUST be emitted
556 public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true)
559 ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target);
562 // Emit this expression for its side effects, not for its value.
563 // The default implementation is to emit the value, and then throw it away.
564 // Subclasses can provide more efficient implementations, but those MUST be equivalent
565 public virtual void EmitSideEffect (EmitContext ec)
568 ec.Emit (OpCodes.Pop);
572 /// Protected constructor. Only derivate types should
573 /// be able to be created
576 protected Expression ()
581 /// Returns a fully formed expression after a MemberLookup
584 public static Expression ExprClassFromMemberInfo (TypeSpec container_type, MemberSpec spec, Location loc)
586 if (spec is EventSpec)
587 return new EventExpr ((EventSpec) spec, loc);
588 if (spec is ConstSpec)
589 return new ConstantExpr ((ConstSpec) spec, loc);
590 if (spec is FieldSpec)
591 return new FieldExpr ((FieldSpec) spec, loc);
592 if (spec is PropertySpec)
593 return new PropertyExpr (container_type, (PropertySpec) spec, loc);
594 if (spec is TypeSpec)
595 return new TypeExpression (((TypeSpec) spec), loc);
601 // FIXME: Probably implement a cache for (t,name,current_access_set)?
603 // This code could use some optimizations, but we need to do some
604 // measurements. For example, we could use a delegate to `flag' when
605 // something can not any longer be a method-group (because it is something
609 // If the return value is an Array, then it is an array of
612 // If the return value is an MemberInfo, it is anything, but a Method
616 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
617 // the arguments here and have MemberLookup return only the methods that
618 // match the argument count/type, unlike we are doing now (we delay this
621 // This is so we can catch correctly attempts to invoke instance methods
622 // from a static body (scan for error 120 in ResolveSimpleName).
625 // FIXME: Potential optimization, have a static ArrayList
628 public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type, string name, int arity,
629 MemberKind mt, BindingRestriction bf, Location loc)
631 return MemberLookup (ctx, container_type, null, queried_type, name, arity, mt, bf, loc);
635 // Lookup type `queried_type' for code in class `container_type' with a qualifier of
636 // `qualifier_type' or null to lookup members in the current class.
638 public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type,
639 TypeSpec qualifier_type, TypeSpec queried_type,
640 string name, int arity, MemberKind mt,
641 BindingRestriction binding, Location loc)
643 var mi = TypeManager.MemberLookup (container_type, qualifier_type,
644 queried_type, mt, binding, name, arity, null);
650 foreach (var mc in mi) {
651 if (mc is MethodSpec)
652 return new MethodGroupExpr (mi, queried_type, loc);
655 ctx.Report.SymbolRelatedToPreviousError (mi [1]);
656 ctx.Report.SymbolRelatedToPreviousError (first);
657 ctx.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
658 first.GetSignatureForError (), mi [1].GetSignatureForError ());
661 if (first is MethodSpec)
662 return new MethodGroupExpr (mi, queried_type, loc);
664 return ExprClassFromMemberInfo (container_type, first, loc);
667 public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type,
668 string name, int arity, BindingRestriction binding, Location loc)
670 return MemberLookup (ctx, container_type, null, queried_type, name, arity,
671 MemberKind.All, binding | BindingRestriction.AccessibleOnly, loc);
674 public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec qualifier_type,
675 TypeSpec queried_type, string name, int arity, BindingRestriction binding, Location loc)
677 return MemberLookup (ctx, container_type, qualifier_type, queried_type,
678 name, arity, MemberKind.All, binding | BindingRestriction.AccessibleOnly, loc);
681 public static MethodGroupExpr MethodLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type,
682 MemberKind kind, string name, int arity, Location loc)
684 return (MethodGroupExpr)MemberLookup (ctx, container_type, null, queried_type, name, arity,
685 kind, BindingRestriction.AccessibleOnly, loc);
689 /// This is a wrapper for MemberLookup that is not used to "probe", but
690 /// to find a final definition. If the final definition is not found, we
691 /// look for private members and display a useful debugging message if we
694 protected Expression MemberLookupFinal (ResolveContext ec, TypeSpec qualifier_type,
695 TypeSpec queried_type, string name, int arity,
696 MemberKind mt, BindingRestriction bf,
701 int errors = ec.Report.Errors;
702 e = MemberLookup (ec.Compiler, ec.CurrentType, qualifier_type, queried_type, name, arity, mt, bf, loc);
704 if (e != null || errors != ec.Report.Errors)
707 // No errors were reported by MemberLookup, but there was an error.
708 return Error_MemberLookupFailed (ec, ec.CurrentType, qualifier_type, queried_type,
709 name, arity, null, mt, bf);
712 protected virtual Expression Error_MemberLookupFailed (ResolveContext ec, TypeSpec container_type, TypeSpec qualifier_type,
713 TypeSpec queried_type, string name, int arity, string class_name,
714 MemberKind mt, BindingRestriction bf)
716 IList<MemberSpec> lookup = null;
717 if (queried_type == null) {
718 class_name = "global::";
720 BindingRestriction restriction = bf & BindingRestriction.DeclaredOnly;
722 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
723 mt, restriction, name, arity, null);
725 if (lookup != null) {
726 Expression e = Error_MemberLookupFailed (ec, queried_type, lookup);
729 // FIXME: This is still very wrong, it should be done inside
730 // OverloadResolve to do correct arguments matching.
731 // Requires MemberLookup accessiblity check removal
733 if (e == null || (mt & (MemberKind.Method | MemberKind.Constructor)) == 0) {
734 var mi = lookup.First ();
735 ec.Report.SymbolRelatedToPreviousError (mi);
736 if ((mi.Modifiers & Modifiers.PROTECTED) != 0 && qualifier_type != null && container_type != null && qualifier_type != container_type &&
737 TypeManager.IsNestedFamilyAccessible (container_type, mi.DeclaringType)) {
738 // Although a derived class can access protected members of
739 // its base class it cannot do so through an instance of the
740 // base class (CS1540). If the qualifier_type is a base of the
741 // ec.CurrentType and the lookup succeeds with the latter one,
742 // then we are in this situation.
743 Error_CannotAccessProtected (ec, loc, mi, qualifier_type, container_type);
745 ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (mi), ec.Report);
752 lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
753 MemberKind.All, BindingRestriction.None, name, -System.Math.Max (1, arity), null);
756 if (lookup == null) {
757 if (class_name != null) {
758 ec.Report.Error (103, loc, "The name `{0}' does not exist in the current context",
761 Error_TypeDoesNotContainDefinition (ec, queried_type, name);
766 var mge = Error_MemberLookupFailed (ec, queried_type, lookup);
767 if (arity > 0 && mge != null) {
768 mge.SetTypeArguments (ec, new TypeArguments (new FullNamedExpression [arity]));
774 protected virtual MemberExpr Error_MemberLookupFailed (ResolveContext ec, TypeSpec type, IList<MemberSpec> members)
776 if (members.Any ((m) => !(m is MethodSpec)))
777 return (MemberExpr) ExprClassFromMemberInfo (type, members.First (), loc);
779 // By default propagate the closest candidates upwards
780 return new MethodGroupExpr (members, type, loc, true);
783 protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc)
785 throw new NotImplementedException ();
788 protected void Error_PointerInsideExpressionTree (ResolveContext ec)
790 ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
794 /// Returns an expression that can be used to invoke operator true
795 /// on the expression if it exists.
797 protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc)
799 return GetOperatorTrueOrFalse (ec, e, true, loc);
803 /// Returns an expression that can be used to invoke operator false
804 /// on the expression if it exists.
806 static public Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc)
808 return GetOperatorTrueOrFalse (ec, e, false, loc);
811 static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc)
813 MethodGroupExpr operator_group;
814 string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False);
815 operator_group = MethodLookup (ec.Compiler, ec.CurrentType, e.Type, MemberKind.Operator, mname, 0, loc) as MethodGroupExpr;
816 if (operator_group == null)
819 Arguments arguments = new Arguments (1);
820 arguments.Add (new Argument (e));
821 operator_group = operator_group.OverloadResolve (
822 ec, ref arguments, false, loc);
824 if (operator_group == null)
827 return new UserOperatorCall (operator_group, arguments, null, loc);
830 public virtual string ExprClassName
834 case ExprClass.Unresolved:
836 case ExprClass.Value:
838 case ExprClass.Variable:
840 case ExprClass.Namespace:
844 case ExprClass.MethodGroup:
845 return "method group";
846 case ExprClass.PropertyAccess:
847 return "property access";
848 case ExprClass.EventAccess:
849 return "event access";
850 case ExprClass.IndexerAccess:
851 return "indexer access";
852 case ExprClass.Nothing:
854 case ExprClass.TypeParameter:
855 return "type parameter";
857 throw new Exception ("Should not happen");
862 /// Reports that we were expecting `expr' to be of class `expected'
864 public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, Location loc)
866 Error_UnexpectedKind (r, mc, expected, ExprClassName, loc);
869 public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, string was, Location loc)
873 name = mc.GetSignatureForError ();
875 name = GetSignatureForError ();
877 r.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected",
878 name, was, expected);
881 public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc)
883 string [] valid = new string [4];
886 if ((flags & ResolveFlags.VariableOrValue) != 0) {
887 valid [count++] = "variable";
888 valid [count++] = "value";
891 if ((flags & ResolveFlags.Type) != 0)
892 valid [count++] = "type";
894 if ((flags & ResolveFlags.MethodGroup) != 0)
895 valid [count++] = "method group";
898 valid [count++] = "unknown";
900 StringBuilder sb = new StringBuilder (valid [0]);
901 for (int i = 1; i < count - 1; i++) {
903 sb.Append (valid [i]);
906 sb.Append ("' or `");
907 sb.Append (valid [count - 1]);
910 ec.Report.Error (119, loc,
911 "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ());
914 public static void UnsafeError (ResolveContext ec, Location loc)
916 UnsafeError (ec.Report, loc);
919 public static void UnsafeError (Report Report, Location loc)
921 Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context");
926 // Returns the size of type `t' if known, otherwise, 0
928 public static int GetTypeSize (TypeSpec t)
930 if (t == TypeManager.int32_type ||
931 t == TypeManager.uint32_type ||
932 t == TypeManager.float_type)
934 else if (t == TypeManager.int64_type ||
935 t == TypeManager.uint64_type ||
936 t == TypeManager.double_type)
938 else if (t == TypeManager.byte_type ||
939 t == TypeManager.sbyte_type ||
940 t == TypeManager.bool_type)
942 else if (t == TypeManager.short_type ||
943 t == TypeManager.char_type ||
944 t == TypeManager.ushort_type)
946 else if (t == TypeManager.decimal_type)
952 protected void Error_CannotCallAbstractBase (ResolveContext ec, string name)
954 ec.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name);
957 protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec)
959 ec.Report.SymbolRelatedToPreviousError (type);
960 if (ec.CurrentInitializerVariable != null) {
961 ec.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
962 TypeManager.CSharpName (type), GetSignatureForError ());
964 ec.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
965 GetSignatureForError ());
970 // Converts `source' to an int, uint, long or ulong.
972 protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source)
974 if (source.type == InternalType.Dynamic) {
975 Arguments args = new Arguments (1);
976 args.Add (new Argument (source));
977 return new DynamicConversion (TypeManager.int32_type, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec);
980 Expression converted;
982 using (ec.Set (ResolveContext.Options.CheckedScope)) {
983 converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc);
984 if (converted == null)
985 converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc);
986 if (converted == null)
987 converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc);
988 if (converted == null)
989 converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc);
991 if (converted == null) {
992 source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false);
998 // Only positive constants are allowed at compile time
1000 Constant c = converted as Constant;
1001 if (c != null && c.IsNegative)
1002 Error_NegativeArrayIndex (ec, source.loc);
1004 // No conversion needed to array index
1005 if (converted.Type == TypeManager.int32_type)
1008 return new ArrayIndexCast (converted).Resolve (ec);
1012 // Derived classes implement this method by cloning the fields that
1013 // could become altered during the Resolve stage
1015 // Only expressions that are created for the parser need to implement
1018 protected virtual void CloneTo (CloneContext clonectx, Expression target)
1020 throw new NotImplementedException (
1022 "CloneTo not implemented for expression {0}", this.GetType ()));
1026 // Clones an expression created by the parser.
1028 // We only support expressions created by the parser so far, not
1029 // expressions that have been resolved (many more classes would need
1030 // to implement CloneTo).
1032 // This infrastructure is here merely for Lambda expressions which
1033 // compile the same code using different type values for the same
1034 // arguments to find the correct overload
1036 public Expression Clone (CloneContext clonectx)
1038 Expression cloned = (Expression) MemberwiseClone ();
1039 CloneTo (clonectx, cloned);
1045 // Implementation of expression to expression tree conversion
1047 public abstract Expression CreateExpressionTree (ResolveContext ec);
1049 protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args)
1051 return CreateExpressionFactoryCall (ec, name, null, args, loc);
1054 protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args)
1056 return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc);
1059 public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc)
1061 return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args);
1064 protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc)
1066 TypeExpr texpr = TypeManager.expression_type_expr;
1067 if (texpr == null) {
1068 TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "Expression", MemberKind.Class, true);
1072 TypeManager.expression_type_expr = texpr = new TypeExpression (t, Location.Null);
1079 // Implemented by all expressions which support conversion from
1080 // compiler expression to invokable runtime expression. Used by
1081 // dynamic C# binder.
1083 public virtual SLE.Expression MakeExpression (BuilderContext ctx)
1085 throw new NotImplementedException ("MakeExpression for " + GetType ());
1090 /// This is just a base class for expressions that can
1091 /// appear on statements (invocations, object creation,
1092 /// assignments, post/pre increment and decrement). The idea
1093 /// being that they would support an extra Emition interface that
1094 /// does not leave a result on the stack.
1096 public abstract class ExpressionStatement : Expression {
1098 public virtual ExpressionStatement ResolveStatement (BlockContext ec)
1100 Expression e = Resolve (ec);
1104 ExpressionStatement es = e as ExpressionStatement;
1106 Error_InvalidExpressionStatement (ec);
1112 /// Requests the expression to be emitted in a `statement'
1113 /// context. This means that no new value is left on the
1114 /// stack after invoking this method (constrasted with
1115 /// Emit that will always leave a value on the stack).
1117 public abstract void EmitStatement (EmitContext ec);
1119 public override void EmitSideEffect (EmitContext ec)
1126 /// This kind of cast is used to encapsulate the child
1127 /// whose type is child.Type into an expression that is
1128 /// reported to return "return_type". This is used to encapsulate
1129 /// expressions which have compatible types, but need to be dealt
1130 /// at higher levels with.
1132 /// For example, a "byte" expression could be encapsulated in one
1133 /// of these as an "unsigned int". The type for the expression
1134 /// would be "unsigned int".
1137 public abstract class TypeCast : Expression
1139 protected readonly Expression child;
1141 protected TypeCast (Expression child, TypeSpec return_type)
1143 eclass = child.eclass;
1144 loc = child.Location;
1149 public Expression Child {
1155 public override Expression CreateExpressionTree (ResolveContext ec)
1157 Arguments args = new Arguments (2);
1158 args.Add (new Argument (child.CreateExpressionTree (ec)));
1159 args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
1161 if (type.IsPointer || child.Type.IsPointer)
1162 Error_PointerInsideExpressionTree (ec);
1164 return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args);
1167 protected override Expression DoResolve (ResolveContext ec)
1169 // This should never be invoked, we are born in fully
1170 // initialized state.
1175 public override void Emit (EmitContext ec)
1180 public override SLE.Expression MakeExpression (BuilderContext ctx)
1182 return ctx.HasSet (BuilderContext.Options.CheckedScope) ?
1183 SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) :
1184 SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ());
1187 protected override void CloneTo (CloneContext clonectx, Expression t)
1192 public override bool IsNull {
1193 get { return child.IsNull; }
1197 public class EmptyCast : TypeCast {
1198 EmptyCast (Expression child, TypeSpec target_type)
1199 : base (child, target_type)
1203 public static Expression Create (Expression child, TypeSpec type)
1205 Constant c = child as Constant;
1207 return new EmptyConstantCast (c, type);
1209 EmptyCast e = child as EmptyCast;
1211 return new EmptyCast (e.child, type);
1213 return new EmptyCast (child, type);
1216 public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1218 child.EmitBranchable (ec, label, on_true);
1221 public override void EmitSideEffect (EmitContext ec)
1223 child.EmitSideEffect (ec);
1228 // Used for predefined class library user casts (no obsolete check, etc.)
1230 public class OperatorCast : TypeCast {
1231 MethodSpec conversion_operator;
1233 public OperatorCast (Expression child, TypeSpec target_type)
1234 : this (child, target_type, false)
1238 public OperatorCast (Expression child, TypeSpec target_type, bool find_explicit)
1239 : base (child, target_type)
1241 conversion_operator = GetConversionOperator (find_explicit);
1242 if (conversion_operator == null)
1243 throw new InternalErrorException ("Outer conversion routine is out of sync");
1246 // Returns the implicit operator that converts from
1247 // 'child.Type' to our target type (type)
1248 MethodSpec GetConversionOperator (bool find_explicit)
1250 string operator_name = find_explicit ? "op_Explicit" : "op_Implicit";
1252 // Operators are always public
1253 var mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberKind.Operator,
1254 BindingRestriction.None, operator_name, 0, null);
1257 mi = TypeManager.MemberLookup (type, type, type, MemberKind.Operator,
1258 BindingRestriction.None, operator_name, 0, null);
1261 foreach (MethodSpec oper in mi) {
1262 AParametersCollection pd = oper.Parameters;
1264 if (pd.Types [0] == child.Type && oper.ReturnType == type)
1271 public override void Emit (EmitContext ec)
1274 ec.Emit (OpCodes.Call, conversion_operator);
1279 /// This is a numeric cast to a Decimal
1281 public class CastToDecimal : OperatorCast {
1282 public CastToDecimal (Expression child)
1283 : this (child, false)
1287 public CastToDecimal (Expression child, bool find_explicit)
1288 : base (child, TypeManager.decimal_type, find_explicit)
1294 /// This is an explicit numeric cast from a Decimal
1296 public class CastFromDecimal : TypeCast
1298 static Dictionary<TypeSpec, MethodSpec> operators;
1300 public CastFromDecimal (Expression child, TypeSpec return_type)
1301 : base (child, return_type)
1303 if (child.Type != TypeManager.decimal_type)
1304 throw new ArgumentException ("Expected decimal child " + child.Type.GetSignatureForError ());
1307 // Returns the explicit operator that converts from an
1308 // express of type System.Decimal to 'type'.
1309 public Expression Resolve ()
1311 if (operators == null) {
1312 var all_oper = TypeManager.MemberLookup (TypeManager.decimal_type,
1313 TypeManager.decimal_type, TypeManager.decimal_type, MemberKind.Operator,
1314 BindingRestriction.None, "op_Explicit", 0, null);
1316 operators = new Dictionary<TypeSpec, MethodSpec> ();
1317 foreach (MethodSpec oper in all_oper) {
1318 AParametersCollection pd = oper.Parameters;
1319 if (pd.Types [0] == TypeManager.decimal_type)
1320 operators.Add (oper.ReturnType, oper);
1324 return operators.ContainsKey (type) ? this : null;
1327 public override void Emit (EmitContext ec)
1331 ec.Emit (OpCodes.Call, operators [type]);
1334 public static void Reset ()
1342 // Constant specialization of EmptyCast.
1343 // We need to special case this since an empty cast of
1344 // a constant is still a constant.
1346 public class EmptyConstantCast : Constant
1348 public Constant child;
1350 public EmptyConstantCast (Constant child, TypeSpec type)
1351 : base (child.Location)
1354 throw new ArgumentNullException ("child");
1357 this.eclass = child.eclass;
1361 public override string AsString ()
1363 return child.AsString ();
1366 public override object GetValue ()
1368 return child.GetValue ();
1371 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1373 if (child.Type == target_type)
1376 // FIXME: check that 'type' can be converted to 'target_type' first
1377 return child.ConvertExplicitly (in_checked_context, target_type);
1380 public override Expression CreateExpressionTree (ResolveContext ec)
1382 Arguments args = Arguments.CreateForExpressionTree (ec, null,
1383 child.CreateExpressionTree (ec),
1384 new TypeOf (new TypeExpression (type, loc), loc));
1387 Error_PointerInsideExpressionTree (ec);
1389 return CreateExpressionFactoryCall (ec, "Convert", args);
1392 public override bool IsDefaultValue {
1393 get { return child.IsDefaultValue; }
1396 public override bool IsNegative {
1397 get { return child.IsNegative; }
1400 public override bool IsNull {
1401 get { return child.IsNull; }
1404 public override bool IsOneInteger {
1405 get { return child.IsOneInteger; }
1408 public override bool IsZeroInteger {
1409 get { return child.IsZeroInteger; }
1412 protected override Expression DoResolve (ResolveContext rc)
1417 public override void Emit (EmitContext ec)
1422 public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1424 child.EmitBranchable (ec, label, on_true);
1426 // Only to make verifier happy
1427 if (TypeManager.IsGenericParameter (type) && child.IsNull)
1428 ec.Emit (OpCodes.Unbox_Any, type);
1431 public override void EmitSideEffect (EmitContext ec)
1433 child.EmitSideEffect (ec);
1436 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec target_type)
1438 // FIXME: Do we need to check user conversions?
1439 if (!Convert.ImplicitStandardConversionExists (this, target_type))
1441 return child.ConvertImplicitly (rc, target_type);
1446 /// This class is used to wrap literals which belong inside Enums
1448 public class EnumConstant : Constant
1450 public Constant Child;
1452 public EnumConstant (Constant child, TypeSpec enum_type)
1453 : base (child.Location)
1456 this.type = enum_type;
1459 protected EnumConstant (Location loc)
1464 protected override Expression DoResolve (ResolveContext rc)
1466 Child = Child.Resolve (rc);
1467 this.eclass = ExprClass.Value;
1471 public override void Emit (EmitContext ec)
1476 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1478 Child.EncodeAttributeValue (rc, enc, Child.Type);
1481 public override void EmitBranchable (EmitContext ec, Label label, bool on_true)
1483 Child.EmitBranchable (ec, label, on_true);
1486 public override void EmitSideEffect (EmitContext ec)
1488 Child.EmitSideEffect (ec);
1491 public override string GetSignatureForError()
1493 return TypeManager.CSharpName (Type);
1496 public override object GetValue ()
1498 return Child.GetValue ();
1501 public override object GetTypedValue ()
1503 // FIXME: runtime is not ready to work with just emited enums
1504 if (!RootContext.StdLib) {
1505 return Child.GetValue ();
1509 // Small workaround for big problem
1510 // System.Enum.ToObject cannot be called on dynamic types
1511 // EnumBuilder has to be used, but we cannot use EnumBuilder
1512 // because it does not properly support generics
1514 // This works only sometimes
1516 if (type.MemberDefinition is TypeContainer)
1517 return Child.GetValue ();
1520 return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ());
1523 public override string AsString ()
1525 return Child.AsString ();
1528 public EnumConstant Increment()
1530 return new EnumConstant (((IntegralConstant) Child).Increment (), type);
1533 public override bool IsDefaultValue {
1535 return Child.IsDefaultValue;
1539 public override bool IsZeroInteger {
1540 get { return Child.IsZeroInteger; }
1543 public override bool IsNegative {
1545 return Child.IsNegative;
1549 public override Constant ConvertExplicitly(bool in_checked_context, TypeSpec target_type)
1551 if (Child.Type == target_type)
1554 return Child.ConvertExplicitly (in_checked_context, target_type);
1557 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type)
1559 if (this.type == type) {
1563 if (!Convert.ImplicitStandardConversionExists (this, type)){
1567 return Child.ConvertImplicitly (rc, type);
1572 /// This kind of cast is used to encapsulate Value Types in objects.
1574 /// The effect of it is to box the value type emitted by the previous
1577 public class BoxedCast : TypeCast {
1579 public BoxedCast (Expression expr, TypeSpec target_type)
1580 : base (expr, target_type)
1582 eclass = ExprClass.Value;
1585 protected override Expression DoResolve (ResolveContext ec)
1587 // This should never be invoked, we are born in fully
1588 // initialized state.
1593 public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
1595 enc.Encode (child.Type);
1596 child.EncodeAttributeValue (rc, enc, child.Type);
1599 public override void Emit (EmitContext ec)
1603 ec.Emit (OpCodes.Box, child.Type);
1606 public override void EmitSideEffect (EmitContext ec)
1608 // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType
1609 // so, we need to emit the box+pop instructions in most cases
1610 if (TypeManager.IsStruct (child.Type) &&
1611 (type == TypeManager.object_type || type == TypeManager.value_type))
1612 child.EmitSideEffect (ec);
1614 base.EmitSideEffect (ec);
1618 public class UnboxCast : TypeCast {
1619 public UnboxCast (Expression expr, TypeSpec return_type)
1620 : base (expr, return_type)
1624 protected override Expression DoResolve (ResolveContext ec)
1626 // This should never be invoked, we are born in fully
1627 // initialized state.
1632 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
1634 if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
1635 ec.Report.Error (445, loc, "Cannot modify the result of an unboxing conversion");
1636 return base.DoResolveLValue (ec, right_side);
1639 public override void Emit (EmitContext ec)
1643 ec.Emit (OpCodes.Unbox_Any, type);
1648 /// This is used to perform explicit numeric conversions.
1650 /// Explicit numeric conversions might trigger exceptions in a checked
1651 /// context, so they should generate the conv.ovf opcodes instead of
1654 public class ConvCast : TypeCast {
1655 public enum Mode : byte {
1656 I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
1658 I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
1659 U2_I1, U2_U1, U2_I2, U2_CH,
1660 I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
1661 U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
1662 I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, I8_I,
1663 U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I,
1664 CH_I1, CH_U1, CH_I2,
1665 R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
1666 R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4,
1672 public ConvCast (Expression child, TypeSpec return_type, Mode m)
1673 : base (child, return_type)
1678 protected override Expression DoResolve (ResolveContext ec)
1680 // This should never be invoked, we are born in fully
1681 // initialized state.
1686 public override string ToString ()
1688 return String.Format ("ConvCast ({0}, {1})", mode, child);
1691 public override void Emit (EmitContext ec)
1695 if (ec.HasSet (EmitContext.Options.CheckedScope)) {
1697 case Mode.I1_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
1698 case Mode.I1_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1699 case Mode.I1_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
1700 case Mode.I1_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
1701 case Mode.I1_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1703 case Mode.U1_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1704 case Mode.U1_CH: /* nothing */ break;
1706 case Mode.I2_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
1707 case Mode.I2_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
1708 case Mode.I2_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1709 case Mode.I2_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
1710 case Mode.I2_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
1711 case Mode.I2_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1713 case Mode.U2_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1714 case Mode.U2_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1715 case Mode.U2_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1716 case Mode.U2_CH: /* nothing */ break;
1718 case Mode.I4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
1719 case Mode.I4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
1720 case Mode.I4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
1721 case Mode.I4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
1722 case Mode.I4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1723 case Mode.I4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
1724 case Mode.I4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1726 case Mode.U4_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1727 case Mode.U4_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1728 case Mode.U4_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1729 case Mode.U4_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1730 case Mode.U4_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1731 case Mode.U4_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1733 case Mode.I8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
1734 case Mode.I8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
1735 case Mode.I8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
1736 case Mode.I8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1737 case Mode.I8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
1738 case Mode.I8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
1739 case Mode.I8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
1740 case Mode.I8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1741 case Mode.I8_I: ec.Emit (OpCodes.Conv_Ovf_U); break;
1743 case Mode.U8_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1744 case Mode.U8_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1745 case Mode.U8_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1746 case Mode.U8_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1747 case Mode.U8_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break;
1748 case Mode.U8_U4: ec.Emit (OpCodes.Conv_Ovf_U4_Un); break;
1749 case Mode.U8_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1750 case Mode.U8_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break;
1751 case Mode.U8_I: ec.Emit (OpCodes.Conv_Ovf_U_Un); break;
1753 case Mode.CH_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break;
1754 case Mode.CH_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break;
1755 case Mode.CH_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break;
1757 case Mode.R4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
1758 case Mode.R4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
1759 case Mode.R4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
1760 case Mode.R4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1761 case Mode.R4_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
1762 case Mode.R4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
1763 case Mode.R4_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break;
1764 case Mode.R4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
1765 case Mode.R4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1767 case Mode.R8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break;
1768 case Mode.R8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break;
1769 case Mode.R8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break;
1770 case Mode.R8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1771 case Mode.R8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break;
1772 case Mode.R8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break;
1773 case Mode.R8_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break;
1774 case Mode.R8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break;
1775 case Mode.R8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break;
1776 case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break;
1778 case Mode.I_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break;
1782 case Mode.I1_U1: ec.Emit (OpCodes.Conv_U1); break;
1783 case Mode.I1_U2: ec.Emit (OpCodes.Conv_U2); break;
1784 case Mode.I1_U4: ec.Emit (OpCodes.Conv_U4); break;
1785 case Mode.I1_U8: ec.Emit (OpCodes.Conv_I8); break;
1786 case Mode.I1_CH: ec.Emit (OpCodes.Conv_U2); break;
1788 case Mode.U1_I1: ec.Emit (OpCodes.Conv_I1); break;
1789 case Mode.U1_CH: ec.Emit (OpCodes.Conv_U2); break;
1791 case Mode.I2_I1: ec.Emit (OpCodes.Conv_I1); break;
1792 case Mode.I2_U1: ec.Emit (OpCodes.Conv_U1); break;
1793 case Mode.I2_U2: ec.Emit (OpCodes.Conv_U2); break;
1794 case Mode.I2_U4: ec.Emit (OpCodes.Conv_U4); break;
1795 case Mode.I2_U8: ec.Emit (OpCodes.Conv_I8); break;
1796 case Mode.I2_CH: ec.Emit (OpCodes.Conv_U2); break;
1798 case Mode.U2_I1: ec.Emit (OpCodes.Conv_I1); break;
1799 case Mode.U2_U1: ec.Emit (OpCodes.Conv_U1); break;
1800 case Mode.U2_I2: ec.Emit (OpCodes.Conv_I2); break;
1801 case Mode.U2_CH: /* nothing */ break;
1803 case Mode.I4_I1: ec.Emit (OpCodes.Conv_I1); break;
1804 case Mode.I4_U1: ec.Emit (OpCodes.Conv_U1); break;
1805 case Mode.I4_I2: ec.Emit (OpCodes.Conv_I2); break;
1806 case Mode.I4_U4: /* nothing */ break;
1807 case Mode.I4_U2: ec.Emit (OpCodes.Conv_U2); break;
1808 case Mode.I4_U8: ec.Emit (OpCodes.Conv_I8); break;
1809 case Mode.I4_CH: ec.Emit (OpCodes.Conv_U2); break;
1811 case Mode.U4_I1: ec.Emit (OpCodes.Conv_I1); break;
1812 case Mode.U4_U1: ec.Emit (OpCodes.Conv_U1); break;
1813 case Mode.U4_I2: ec.Emit (OpCodes.Conv_I2); break;
1814 case Mode.U4_U2: ec.Emit (OpCodes.Conv_U2); break;
1815 case Mode.U4_I4: /* nothing */ break;
1816 case Mode.U4_CH: ec.Emit (OpCodes.Conv_U2); break;
1818 case Mode.I8_I1: ec.Emit (OpCodes.Conv_I1); break;
1819 case Mode.I8_U1: ec.Emit (OpCodes.Conv_U1); break;
1820 case Mode.I8_I2: ec.Emit (OpCodes.Conv_I2); break;
1821 case Mode.I8_U2: ec.Emit (OpCodes.Conv_U2); break;
1822 case Mode.I8_I4: ec.Emit (OpCodes.Conv_I4); break;
1823 case Mode.I8_U4: ec.Emit (OpCodes.Conv_U4); break;
1824 case Mode.I8_U8: /* nothing */ break;
1825 case Mode.I8_CH: ec.Emit (OpCodes.Conv_U2); break;
1826 case Mode.I8_I: ec.Emit (OpCodes.Conv_U); break;
1828 case Mode.U8_I1: ec.Emit (OpCodes.Conv_I1); break;
1829 case Mode.U8_U1: ec.Emit (OpCodes.Conv_U1); break;
1830 case Mode.U8_I2: ec.Emit (OpCodes.Conv_I2); break;
1831 case Mode.U8_U2: ec.Emit (OpCodes.Conv_U2); break;
1832 case Mode.U8_I4: ec.Emit (OpCodes.Conv_I4); break;
1833 case Mode.U8_U4: ec.Emit (OpCodes.Conv_U4); break;
1834 case Mode.U8_I8: /* nothing */ break;
1835 case Mode.U8_CH: ec.Emit (OpCodes.Conv_U2); break;
1836 case Mode.U8_I: ec.Emit (OpCodes.Conv_U); break;
1838 case Mode.CH_I1: ec.Emit (OpCodes.Conv_I1); break;
1839 case Mode.CH_U1: ec.Emit (OpCodes.Conv_U1); break;
1840 case Mode.CH_I2: ec.Emit (OpCodes.Conv_I2); break;
1842 case Mode.R4_I1: ec.Emit (OpCodes.Conv_I1); break;
1843 case Mode.R4_U1: ec.Emit (OpCodes.Conv_U1); break;
1844 case Mode.R4_I2: ec.Emit (OpCodes.Conv_I2); break;
1845 case Mode.R4_U2: ec.Emit (OpCodes.Conv_U2); break;
1846 case Mode.R4_I4: ec.Emit (OpCodes.Conv_I4); break;
1847 case Mode.R4_U4: ec.Emit (OpCodes.Conv_U4); break;
1848 case Mode.R4_I8: ec.Emit (OpCodes.Conv_I8); break;
1849 case Mode.R4_U8: ec.Emit (OpCodes.Conv_U8); break;
1850 case Mode.R4_CH: ec.Emit (OpCodes.Conv_U2); break;
1852 case Mode.R8_I1: ec.Emit (OpCodes.Conv_I1); break;
1853 case Mode.R8_U1: ec.Emit (OpCodes.Conv_U1); break;
1854 case Mode.R8_I2: ec.Emit (OpCodes.Conv_I2); break;
1855 case Mode.R8_U2: ec.Emit (OpCodes.Conv_U2); break;
1856 case Mode.R8_I4: ec.Emit (OpCodes.Conv_I4); break;
1857 case Mode.R8_U4: ec.Emit (OpCodes.Conv_U4); break;
1858 case Mode.R8_I8: ec.Emit (OpCodes.Conv_I8); break;
1859 case Mode.R8_U8: ec.Emit (OpCodes.Conv_U8); break;
1860 case Mode.R8_CH: ec.Emit (OpCodes.Conv_U2); break;
1861 case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break;
1863 case Mode.I_I8: ec.Emit (OpCodes.Conv_U8); break;
1869 public class OpcodeCast : TypeCast {
1872 public OpcodeCast (Expression child, TypeSpec return_type, OpCode op)
1873 : base (child, return_type)
1878 protected override Expression DoResolve (ResolveContext ec)
1880 // This should never be invoked, we are born in fully
1881 // initialized state.
1886 public override void Emit (EmitContext ec)
1892 public TypeSpec UnderlyingType {
1893 get { return child.Type; }
1898 /// This kind of cast is used to encapsulate a child and cast it
1899 /// to the class requested
1901 public sealed class ClassCast : TypeCast {
1902 readonly bool forced;
1904 public ClassCast (Expression child, TypeSpec return_type)
1905 : base (child, return_type)
1909 public ClassCast (Expression child, TypeSpec return_type, bool forced)
1910 : base (child, return_type)
1912 this.forced = forced;
1915 public override void Emit (EmitContext ec)
1919 bool gen = TypeManager.IsGenericParameter (child.Type);
1921 ec.Emit (OpCodes.Box, child.Type);
1923 if (type.IsGenericParameter) {
1924 ec.Emit (OpCodes.Unbox_Any, type);
1931 ec.Emit (OpCodes.Castclass, type);
1936 // Created during resolving pahse when an expression is wrapped or constantified
1937 // and original expression can be used later (e.g. for expression trees)
1939 public class ReducedExpression : Expression
1941 sealed class ReducedConstantExpression : EmptyConstantCast
1943 readonly Expression orig_expr;
1945 public ReducedConstantExpression (Constant expr, Expression orig_expr)
1946 : base (expr, expr.Type)
1948 this.orig_expr = orig_expr;
1951 public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec target_type)
1953 Constant c = base.ConvertImplicitly (rc, target_type);
1955 c = new ReducedConstantExpression (c, orig_expr);
1960 public override Expression CreateExpressionTree (ResolveContext ec)
1962 return orig_expr.CreateExpressionTree (ec);
1965 public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
1967 Constant c = base.ConvertExplicitly (in_checked_context, target_type);
1969 c = new ReducedConstantExpression (c, orig_expr);
1974 sealed class ReducedExpressionStatement : ExpressionStatement
1976 readonly Expression orig_expr;
1977 readonly ExpressionStatement stm;
1979 public ReducedExpressionStatement (ExpressionStatement stm, Expression orig)
1981 this.orig_expr = orig;
1983 this.loc = orig.Location;
1986 public override Expression CreateExpressionTree (ResolveContext ec)
1988 return orig_expr.CreateExpressionTree (ec);
1991 protected override Expression DoResolve (ResolveContext ec)
1993 eclass = stm.eclass;
1998 public override void Emit (EmitContext ec)
2003 public override void EmitStatement (EmitContext ec)
2005 stm.EmitStatement (ec);
2009 readonly Expression expr, orig_expr;
2011 private ReducedExpression (Expression expr, Expression orig_expr)
2014 this.eclass = expr.eclass;
2015 this.type = expr.Type;
2016 this.orig_expr = orig_expr;
2017 this.loc = orig_expr.Location;
2021 // Creates fully resolved expression switcher
2023 public static Constant Create (Constant expr, Expression original_expr)
2025 if (expr.eclass == ExprClass.Unresolved)
2026 throw new ArgumentException ("Unresolved expression");
2028 return new ReducedConstantExpression (expr, original_expr);
2031 public static ExpressionStatement Create (ExpressionStatement s, Expression orig)
2033 return new ReducedExpressionStatement (s, orig);
2037 // Creates unresolved reduce expression. The original expression has to be
2040 public static Expression Create (Expression expr, Expression original_expr)
2042 Constant c = expr as Constant;
2044 return Create (c, original_expr);
2046 ExpressionStatement s = expr as ExpressionStatement;
2048 return Create (s, original_expr);
2050 if (expr.eclass == ExprClass.Unresolved)
2051 throw new ArgumentException ("Unresolved expression");
2053 return new ReducedExpression (expr, original_expr);
2056 public override Expression CreateExpressionTree (ResolveContext ec)
2058 return orig_expr.CreateExpressionTree (ec);
2061 protected override Expression DoResolve (ResolveContext ec)
2066 public override void Emit (EmitContext ec)
2071 public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
2073 expr.EmitBranchable (ec, target, on_true);
2076 public override SLE.Expression MakeExpression (BuilderContext ctx)
2078 return orig_expr.MakeExpression (ctx);
2083 // Standard composite pattern
2085 public abstract class CompositeExpression : Expression
2089 protected CompositeExpression (Expression expr)
2092 this.loc = expr.Location;
2095 public override Expression CreateExpressionTree (ResolveContext ec)
2097 return expr.CreateExpressionTree (ec);
2100 public Expression Child {
2101 get { return expr; }
2104 protected override Expression DoResolve (ResolveContext ec)
2106 expr = expr.Resolve (ec);
2109 eclass = expr.eclass;
2115 public override void Emit (EmitContext ec)
2120 public override bool IsNull {
2121 get { return expr.IsNull; }
2126 // Base of expressions used only to narrow resolve flow
2128 public abstract class ShimExpression : Expression
2130 protected Expression expr;
2132 protected ShimExpression (Expression expr)
2137 protected override void CloneTo (CloneContext clonectx, Expression t)
2142 ShimExpression target = (ShimExpression) t;
2143 target.expr = expr.Clone (clonectx);
2146 public override Expression CreateExpressionTree (ResolveContext ec)
2148 throw new NotSupportedException ("ET");
2151 public override void Emit (EmitContext ec)
2153 throw new InternalErrorException ("Missing Resolve call");
2156 public Expression Expr {
2157 get { return expr; }
2162 // Unresolved type name expressions
2164 public abstract class ATypeNameExpression : FullNamedExpression
2167 protected TypeArguments targs;
2169 protected ATypeNameExpression (string name, Location l)
2175 protected ATypeNameExpression (string name, TypeArguments targs, Location l)
2182 protected ATypeNameExpression (string name, int arity, Location l)
2183 : this (name, new UnboundTypeArguments (arity), l)
2189 protected int Arity {
2191 return targs == null ? 0 : targs.Count;
2195 public bool HasTypeArguments {
2197 return targs != null && !targs.IsEmpty;
2201 public string Name {
2210 public TypeArguments TypeArguments {
2218 public override bool Equals (object obj)
2220 ATypeNameExpression atne = obj as ATypeNameExpression;
2221 return atne != null && atne.Name == Name &&
2222 (targs == null || targs.Equals (atne.targs));
2225 public override int GetHashCode ()
2227 return Name.GetHashCode ();
2230 // TODO: Move it to MemberCore
2231 public static string GetMemberType (MemberCore mc)
2237 if (mc is FieldBase)
2239 if (mc is MethodCore)
2241 if (mc is EnumMember)
2249 public override string GetSignatureForError ()
2251 if (targs != null) {
2252 return Name + "<" + targs.GetSignatureForError () + ">";
2260 /// SimpleName expressions are formed of a single word and only happen at the beginning
2261 /// of a dotted-name.
2263 public class SimpleName : ATypeNameExpression
2265 public SimpleName (string name, Location l)
2270 public SimpleName (string name, TypeArguments args, Location l)
2271 : base (name, args, l)
2275 public SimpleName (string name, int arity, Location l)
2276 : base (name, arity, l)
2280 public SimpleName GetMethodGroup ()
2282 return new SimpleName (Name, targs, loc);
2285 public static void Error_ObjectRefRequired (ResolveContext ec, Location l, string name)
2287 if (ec.HasSet (ResolveContext.Options.FieldInitializerScope))
2288 ec.Report.Error (236, l,
2289 "A field initializer cannot reference the nonstatic field, method, or property `{0}'",
2292 ec.Report.Error (120, l,
2293 "An object reference is required to access non-static member `{0}'",
2297 protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec)
2299 if (ec.CurrentType != null) {
2300 if (ec.CurrentMemberDefinition != null) {
2301 MemberCore mc = ec.CurrentMemberDefinition.Parent.GetDefinition (Name);
2303 Error_UnexpectedKind (ec.Compiler.Report, mc, "type", GetMemberType (mc), loc);
2309 // TODO MemberCache: Implement
2311 string ns = ec.CurrentType.Namespace;
2312 string fullname = (ns.Length > 0) ? ns + "." + Name : Name;
2313 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
2314 var type = a.GetType (fullname);
2316 ec.Compiler.Report.SymbolRelatedToPreviousError (type);
2317 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type), ec.Compiler.Report);
2322 if (ec.CurrentTypeDefinition != null) {
2323 TypeSpec t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name);
2325 Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, t, loc);
2332 FullNamedExpression retval = ec.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), loc, true);
2333 if (retval != null) {
2334 Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc, retval.Type, Arity);
2336 var te = retval as TypeExpr;
2337 if (HasTypeArguments && te != null && !te.Type.IsGeneric)
2338 retval.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc);
2340 Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, retval.Type, loc);
2345 NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Compiler.Report);
2348 public bool IdenticalNameAndTypeName (IMemberContext mc, Expression resolved_to, Location loc)
2350 if (resolved_to == null || resolved_to.Type == null)
2353 if (resolved_to.Type is ElementTypeSpec || resolved_to.Type is InternalType)
2356 return resolved_to.Type.Name == Name &&
2357 (mc.LookupNamespaceOrType (Name, Arity, loc, /* ignore_cs0104 = */ true) != null);
2360 protected override Expression DoResolve (ResolveContext ec)
2362 return SimpleNameResolve (ec, null, false);
2365 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
2367 return SimpleNameResolve (ec, right_side, false);
2370 public Expression DoResolve (ResolveContext ec, bool intermediate)
2372 return SimpleNameResolve (ec, null, intermediate);
2375 static bool IsNestedChild (TypeSpec t, TypeSpec parent)
2377 while (parent != null) {
2378 if (TypeManager.IsNestedChildOf (t, parent))
2381 parent = parent.BaseType;
2387 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2389 int errors = ec.Compiler.Report.Errors;
2390 FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, loc, /*ignore_cs0104=*/ false);
2393 if (HasTypeArguments && fne.Type != null && TypeManager.IsGenericType (fne.Type)) {
2394 GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc);
2395 return ct.ResolveAsTypeStep (ec, false);
2401 if (!HasTypeArguments && Name == "dynamic" &&
2402 RootContext.Version > LanguageVersion.V_3 &&
2403 RootContext.MetadataCompatibilityVersion > MetadataVersion.v2) {
2405 if (!PredefinedAttributes.Get.Dynamic.IsDefined) {
2406 ec.Compiler.Report.Error (1980, Location,
2407 "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?",
2408 PredefinedAttributes.Get.Dynamic.GetSignatureForError ());
2411 return new DynamicTypeExpr (loc);
2414 if (silent || errors != ec.Compiler.Report.Errors)
2417 Error_TypeOrNamespaceNotFound (ec);
2421 Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
2423 Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
2428 if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location))
2435 /// 7.5.2: Simple Names.
2437 /// Local Variables and Parameters are handled at
2438 /// parse time, so they never occur as SimpleNames.
2440 /// The `intermediate' flag is used by MemberAccess only
2441 /// and it is used to inform us that it is ok for us to
2442 /// avoid the static check, because MemberAccess might end
2443 /// up resolving the Name as a Type name and the access as
2444 /// a static type access.
2446 /// ie: Type Type; .... { Type.GetType (""); }
2448 /// Type is both an instance variable and a Type; Type.GetType
2449 /// is the static method not an instance method of type.
2451 Expression DoSimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate)
2453 Expression e = null;
2456 // Stage 1: Performed by the parser (binding to locals or parameters).
2458 Block current_block = ec.CurrentBlock;
2459 if (current_block != null){
2460 LocalInfo vi = current_block.GetLocalInfo (Name);
2462 e = new LocalVariableReference (ec.CurrentBlock, Name, loc);
2464 if (right_side != null) {
2465 e = e.ResolveLValue (ec, right_side);
2468 using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
2469 e = e.Resolve (ec, ResolveFlags.VariableOrValue);
2472 e = e.Resolve (ec, ResolveFlags.VariableOrValue);
2476 if (HasTypeArguments && e != null)
2477 e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0);
2482 e = current_block.Toplevel.GetParameterReference (Name, loc);
2484 if (right_side != null)
2485 e = e.ResolveLValue (ec, right_side);
2489 if (HasTypeArguments && e != null)
2490 e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0);
2497 // Stage 2: Lookup members
2499 int arity = HasTypeArguments ? Arity : -1;
2500 // TypeSpec almost_matched_type = null;
2501 // IList<MemberSpec> almost_matched = null;
2502 for (TypeSpec lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) {
2503 e = MemberLookup (ec.Compiler, ec.CurrentType, lookup_ds, Name, arity, BindingRestriction.NoOverrides, loc);
2505 PropertyExpr pe = e as PropertyExpr;
2507 // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
2508 // it doesn't know which accessor to check permissions against
2509 if (pe.PropertyInfo.Kind == MemberKind.Property && pe.IsAccessibleFrom (ec.CurrentType, right_side != null))
2511 } else if (e is EventExpr) {
2512 if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType))
2514 } else if (HasTypeArguments && e is TypeExpression) {
2515 e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false);
2523 if (almost_matched == null && almost_matched_members.Count > 0) {
2524 almost_matched_type = lookup_ds;
2525 almost_matched = new List<MemberSpec>(almost_matched_members);
2532 if (almost_matched == null && almost_matched_members.Count > 0) {
2533 almost_matched_type = ec.CurrentType;
2534 almost_matched = new List<MemberSpec> (almost_matched_members);
2537 e = ResolveAsTypeStep (ec, true);
2541 if (current_block != null) {
2542 IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
2544 LocalInfo li = ikv as LocalInfo;
2545 // Supress CS0219 warning
2549 Error_VariableIsUsedBeforeItIsDeclared (ec.Report, Name);
2554 if (RootContext.EvalMode){
2555 var fi = Evaluator.LookupField (Name);
2557 return new FieldExpr (fi.Item1, loc).Resolve (ec);
2560 if (almost_matched != null)
2561 almost_matched_members = almost_matched;
2562 if (almost_matched_type == null)
2563 almost_matched_type = ec.CurrentType;
2565 string type_name = ec.MemberContext.CurrentType == null ? null : ec.MemberContext.CurrentType.Name;
2566 return Error_MemberLookupFailed (ec, ec.CurrentType, null, ec.CurrentType, Name, arity,
2567 type_name, MemberKind.All, BindingRestriction.AccessibleOnly);
2570 if (e is MemberExpr) {
2571 MemberExpr me = (MemberExpr) e;
2574 if (me.IsInstance) {
2575 if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) {
2577 // Note that an MemberExpr can be both IsInstance and IsStatic.
2578 // An unresolved MethodGroupExpr can contain both kinds of methods
2579 // and each predicate is true if the MethodGroupExpr contains
2580 // at least one of that kind of method.
2584 (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) {
2585 Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ());
2590 // Pass the buck to MemberAccess and Invocation.
2592 left = EmptyExpression.Null;
2594 left = ec.GetThis (loc);
2597 left = new TypeExpression (ec.CurrentType, loc);
2600 me = me.ResolveMemberAccess (ec, left, loc, null);
2604 if (HasTypeArguments) {
2605 if (!targs.Resolve (ec))
2608 me.SetTypeArguments (ec, targs);
2611 if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) &&
2612 TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2613 me.InstanceExpression.Type != me.DeclaringType &&
2614 !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) &&
2615 (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) {
2616 ec.Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'",
2617 TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type));
2621 return (right_side != null)
2622 ? me.DoResolveLValue (ec, right_side)
2631 /// Represents a namespace or a type. The name of the class was inspired by
2632 /// section 10.8.1 (Fully Qualified Names).
2634 public abstract class FullNamedExpression : Expression
2636 protected override void CloneTo (CloneContext clonectx, Expression target)
2638 // Do nothing, most unresolved type expressions cannot be
2639 // resolved to different type
2642 public override Expression CreateExpressionTree (ResolveContext ec)
2644 throw new NotSupportedException ("ET");
2647 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2652 public override void Emit (EmitContext ec)
2654 throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree",
2655 GetSignatureForError ());
2660 /// Expression that evaluates to a type
2662 public abstract class TypeExpr : FullNamedExpression {
2663 public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent)
2665 TypeExpr t = DoResolveAsTypeStep (ec);
2669 eclass = ExprClass.Type;
2673 protected override Expression DoResolve (ResolveContext ec)
2675 return ResolveAsTypeTerminal (ec, false);
2678 public virtual bool CheckAccessLevel (IMemberContext mc)
2680 DeclSpace c = mc.CurrentMemberDefinition as DeclSpace;
2682 c = mc.CurrentMemberDefinition.Parent;
2684 return c.CheckAccessLevel (Type);
2687 protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec);
2689 public override bool Equals (object obj)
2691 TypeExpr tobj = obj as TypeExpr;
2695 return Type == tobj.Type;
2698 public override int GetHashCode ()
2700 return Type.GetHashCode ();
2705 /// Fully resolved Expression that already evaluated to a type
2707 public class TypeExpression : TypeExpr {
2708 public TypeExpression (TypeSpec t, Location l)
2711 eclass = ExprClass.Type;
2715 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
2720 public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent)
2727 // Used to create types from a fully qualified name. These are just used
2728 // by the parser to setup the core types.
2730 public sealed class TypeLookupExpression : TypeExpr {
2732 public TypeLookupExpression (TypeSpec type)
2734 eclass = ExprClass.Type;
2738 protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec)
2745 /// This class denotes an expression which evaluates to a member
2746 /// of a struct or a class.
2748 public abstract class MemberExpr : Expression
2750 protected bool is_base;
2753 /// The name of this member.
2755 public abstract string Name {
2760 // When base.member is used
2762 public bool IsBase {
2763 get { return is_base; }
2764 set { is_base = value; }
2768 /// Whether this is an instance member.
2770 public abstract bool IsInstance {
2775 /// Whether this is a static member.
2777 public abstract bool IsStatic {
2782 /// The type which declares this member.
2784 public abstract TypeSpec DeclaringType {
2789 /// The instance expression associated with this member, if it's a
2790 /// non-static member.
2792 public Expression InstanceExpression;
2794 public static void error176 (ResolveContext ec, Location loc, string name)
2796 ec.Report.Error (176, loc, "Static member `{0}' cannot be accessed " +
2797 "with an instance reference, qualify it with a type name instead", name);
2800 public static void Error_BaseAccessInExpressionTree (ResolveContext ec, Location loc)
2802 ec.Report.Error (831, loc, "An expression tree may not contain a base access");
2805 public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
2806 SimpleName original)
2810 // original == null || original.Resolve (...) ==> left
2813 if (left is TypeExpr) {
2814 left = ((TypeExpr) left).ResolveAsTypeTerminal (ec, false);
2818 // TODO: Same problem as in class.cs, TypeTerminal does not
2819 // always do all necessary checks
2820 ObsoleteAttribute oa = left.Type.GetAttributeObsolete ();
2821 if (oa != null && !ec.IsObsolete) {
2822 AttributeTester.Report_ObsoleteMessage (oa, left.GetSignatureForError (), loc, ec.Report);
2825 // GenericTypeExpr ct = left as GenericTypeExpr;
2826 // if (ct != null && !ct.CheckConstraints (ec))
2831 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
2839 if (original != null && original.IdenticalNameAndTypeName (ec, left, loc))
2842 return ResolveExtensionMemberAccess (ec, left);
2845 InstanceExpression = left;
2849 protected virtual MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
2851 error176 (ec, loc, GetSignatureForError ());
2855 protected void EmitInstance (EmitContext ec, bool prepare_for_load)
2860 if (InstanceExpression == EmptyExpression.Null) {
2861 // FIXME: This should not be here at all
2862 SimpleName.Error_ObjectRefRequired (new ResolveContext (ec.MemberContext), loc, GetSignatureForError ());
2866 if (TypeManager.IsValueType (InstanceExpression.Type)) {
2867 if (InstanceExpression is IMemoryLocation) {
2868 ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore);
2870 LocalTemporary t = new LocalTemporary (InstanceExpression.Type);
2871 InstanceExpression.Emit (ec);
2873 t.AddressOf (ec, AddressOp.Store);
2876 InstanceExpression.Emit (ec);
2878 if (prepare_for_load)
2879 ec.Emit (OpCodes.Dup);
2882 public virtual void SetTypeArguments (ResolveContext ec, TypeArguments ta)
2884 // TODO: need to get correct member type
2885 ec.Report.Error (307, loc, "The property `{0}' cannot be used with type arguments",
2886 GetSignatureForError ());
2891 /// Represents group of extension methods
2893 public class ExtensionMethodGroupExpr : MethodGroupExpr
2895 readonly NamespaceEntry namespace_entry;
2896 public Expression ExtensionExpression;
2898 public ExtensionMethodGroupExpr (List<MethodSpec> list, NamespaceEntry n, TypeSpec extensionType, Location l)
2899 : base (list.Cast<MemberSpec>().ToList (), extensionType, l)
2901 this.namespace_entry = n;
2904 public override bool IsStatic {
2905 get { return true; }
2908 public bool IsTopLevel {
2909 get { return namespace_entry == null; }
2912 public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, bool may_fail, Location loc)
2914 if (arguments == null)
2915 arguments = new Arguments (1);
2917 arguments.Insert (0, new Argument (ExtensionExpression));
2918 MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc);
2920 // Store resolved argument and restore original arguments
2922 arguments.RemoveAt (0); // Clean-up modified arguments for error reporting
2927 MethodGroupExpr ResolveOverloadExtensions (ResolveContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc)
2929 // Use normal resolve rules
2930 MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc);
2938 int arity = type_arguments == null ? -1 : type_arguments.Count;
2939 ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, arity, loc);
2941 return base.OverloadResolve (ec, ref arguments, false, loc);
2943 e.ExtensionExpression = ExtensionExpression;
2944 e.SetTypeArguments (ec, type_arguments);
2945 return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc);
2950 /// MethodGroupExpr represents a group of method candidates which
2951 /// can be resolved to the best method overload
2953 public class MethodGroupExpr : MemberExpr
2955 public interface IErrorHandler
2957 bool AmbiguousCall (ResolveContext ec, MethodSpec ambiguous);
2958 bool NoExactMatch (ResolveContext ec, MethodSpec method);
2961 public IErrorHandler CustomErrorHandler;
2962 public IList<MemberSpec> Methods;
2963 MethodSpec best_candidate;
2964 // TODO: make private
2965 public TypeArguments type_arguments;
2966 bool identical_type_name;
2967 bool has_inaccessible_candidates_only;
2968 TypeSpec delegate_type;
2969 TypeSpec queried_type;
2971 public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location l)
2977 public MethodGroupExpr (MethodSpec m, TypeSpec type, Location l)
2980 Methods = new List<MemberSpec> (1) { m };
2983 public MethodGroupExpr (IList<MemberSpec> mi, TypeSpec type, Location l, bool inacessibleCandidatesOnly)
2984 : this (mi, type, l)
2986 has_inaccessible_candidates_only = inacessibleCandidatesOnly;
2989 protected MethodGroupExpr (TypeSpec type, Location loc)
2992 eclass = ExprClass.MethodGroup;
2993 this.type = InternalType.MethodGroup;
2994 queried_type = type;
2997 public override TypeSpec DeclaringType {
2999 return queried_type;
3003 public MethodSpec BestCandidate {
3005 return best_candidate;
3009 public TypeSpec DelegateType {
3011 delegate_type = value;
3015 public bool IdenticalTypeName {
3017 return identical_type_name;
3021 public override string GetSignatureForError ()
3023 if (best_candidate != null)
3024 return best_candidate.GetSignatureForError ();
3026 return Methods.First ().GetSignatureForError ();
3029 public override string Name {
3031 return Methods.First ().Name;
3035 public override bool IsInstance {
3037 if (best_candidate != null)
3038 return !best_candidate.IsStatic;
3040 foreach (var mb in Methods)
3048 public override bool IsStatic {
3050 if (best_candidate != null)
3051 return best_candidate.IsStatic;
3053 foreach (var mb in Methods)
3061 public static explicit operator MethodSpec (MethodGroupExpr mg)
3063 return mg.best_candidate;
3067 // 7.4.3.3 Better conversion from expression
3068 // Returns : 1 if a->p is better,
3069 // 2 if a->q is better,
3070 // 0 if neither is better
3072 static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q)
3074 TypeSpec argument_type = a.Type;
3075 if (argument_type == InternalType.AnonymousMethod && RootContext.Version > LanguageVersion.ISO_2) {
3077 // Uwrap delegate from Expression<T>
3079 if (p.GetDefinition () == TypeManager.expression_type) {
3080 p = TypeManager.GetTypeArguments (p) [0];
3082 if (q.GetDefinition () == TypeManager.expression_type) {
3083 q = TypeManager.GetTypeArguments (q) [0];
3086 p = Delegate.GetInvokeMethod (ec.Compiler, p).ReturnType;
3087 q = Delegate.GetInvokeMethod (ec.Compiler, q).ReturnType;
3088 if (p == TypeManager.void_type && q != TypeManager.void_type)
3090 if (q == TypeManager.void_type && p != TypeManager.void_type)
3093 if (argument_type == p)
3096 if (argument_type == q)
3100 return BetterTypeConversion (ec, p, q);
3104 // 7.4.3.4 Better conversion from type
3106 public static int BetterTypeConversion (ResolveContext ec, TypeSpec p, TypeSpec q)
3108 if (p == null || q == null)
3109 throw new InternalErrorException ("BetterTypeConversion got a null conversion");
3111 if (p == TypeManager.int32_type) {
3112 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3114 } else if (p == TypeManager.int64_type) {
3115 if (q == TypeManager.uint64_type)
3117 } else if (p == TypeManager.sbyte_type) {
3118 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
3119 q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3121 } else if (p == TypeManager.short_type) {
3122 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
3123 q == TypeManager.uint64_type)
3125 } else if (p == InternalType.Dynamic) {
3126 if (q == TypeManager.object_type)
3130 if (q == TypeManager.int32_type) {
3131 if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3133 } if (q == TypeManager.int64_type) {
3134 if (p == TypeManager.uint64_type)
3136 } else if (q == TypeManager.sbyte_type) {
3137 if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
3138 p == TypeManager.uint32_type || p == TypeManager.uint64_type)
3140 } if (q == TypeManager.short_type) {
3141 if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
3142 p == TypeManager.uint64_type)
3144 } else if (q == InternalType.Dynamic) {
3145 if (p == TypeManager.object_type)
3149 // TODO: this is expensive
3150 Expression p_tmp = new EmptyExpression (p);
3151 Expression q_tmp = new EmptyExpression (q);
3153 bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
3154 bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
3156 if (p_to_q && !q_to_p)
3159 if (q_to_p && !p_to_q)
3166 /// Determines "Better function" between candidate
3167 /// and the current best match
3170 /// Returns a boolean indicating :
3171 /// false if candidate ain't better
3172 /// true if candidate is better than the current best match
3174 static bool BetterFunction (ResolveContext ec, Arguments args, int argument_count,
3175 MethodSpec candidate, bool candidate_params,
3176 MethodSpec best, bool best_params)
3178 AParametersCollection candidate_pd = candidate.Parameters;
3179 AParametersCollection best_pd = best.Parameters;
3181 bool better_at_least_one = false;
3183 for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx)
3185 Argument a = args [j];
3187 // Provided default argument value is never better
3188 if (a.IsDefaultArgument && candidate_params == best_params)
3191 TypeSpec ct = candidate_pd.Types [c_idx];
3192 TypeSpec bt = best_pd.Types [b_idx];
3194 if (candidate_params && candidate_pd.FixedParameters [c_idx].ModFlags == Parameter.Modifier.PARAMS)
3196 ct = TypeManager.GetElementType (ct);
3200 if (best_params && best_pd.FixedParameters [b_idx].ModFlags == Parameter.Modifier.PARAMS)
3202 bt = TypeManager.GetElementType (bt);
3206 if (TypeManager.IsEqual (ct, bt))
3210 int result = BetterExpressionConversion (ec, a, ct, bt);
3212 // for each argument, the conversion to 'ct' should be no worse than
3213 // the conversion to 'bt'.
3217 // for at least one argument, the conversion to 'ct' should be better than
3218 // the conversion to 'bt'.
3220 better_at_least_one = true;
3223 if (better_at_least_one)
3227 // This handles the case
3229 // Add (float f1, float f2, float f3);
3230 // Add (params decimal [] foo);
3232 // The call Add (3, 4, 5) should be ambiguous. Without this check, the
3233 // first candidate would've chosen as better.
3239 // The two methods have equal parameter types. Now apply tie-breaking rules
3241 if (best.IsGeneric) {
3242 if (!candidate.IsGeneric)
3244 } else if (candidate.IsGeneric) {
3249 // This handles the following cases:
3251 // Trim () is better than Trim (params char[] chars)
3252 // Concat (string s1, string s2, string s3) is better than
3253 // Concat (string s1, params string [] srest)
3254 // Foo (int, params int [] rest) is better than Foo (params int [] rest)
3256 if (!candidate_params && best_params)
3258 if (candidate_params && !best_params)
3261 int candidate_param_count = candidate_pd.Count;
3262 int best_param_count = best_pd.Count;
3264 if (candidate_param_count != best_param_count)
3265 // can only happen if (candidate_params && best_params)
3266 return candidate_param_count > best_param_count && best_pd.HasParams;
3269 // Both methods have the same number of parameters, and the parameters have equal types
3270 // Pick the "more specific" signature using rules over original (non-inflated) types
3272 var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters;
3273 var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters;
3275 bool specific_at_least_once = false;
3276 for (int j = 0; j < candidate_param_count; ++j)
3278 var ct = candidate_def_pd.Types [j];
3279 var bt = best_def_pd.Types [j];
3282 TypeSpec specific = MoreSpecific (ct, bt);
3286 specific_at_least_once = true;
3289 if (specific_at_least_once)
3292 // FIXME: handle lifted operators
3298 protected override MemberExpr ResolveExtensionMemberAccess (ResolveContext ec, Expression left)
3301 return base.ResolveExtensionMemberAccess (ec, left);
3304 // When left side is an expression and at least one candidate method is
3305 // static, it can be extension method
3307 InstanceExpression = left;
3311 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
3312 SimpleName original)
3314 if (!(left is TypeExpr) &&
3315 original != null && original.IdenticalNameAndTypeName (ec, left, loc))
3316 identical_type_name = true;
3318 return base.ResolveMemberAccess (ec, left, loc, original);
3321 public override Expression CreateExpressionTree (ResolveContext ec)
3323 if (best_candidate == null) {
3324 ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group");
3328 if (best_candidate.IsConditionallyExcluded (loc))
3329 ec.Report.Error (765, loc,
3330 "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
3332 return new TypeOfMethod (best_candidate, loc);
3335 protected override Expression DoResolve (ResolveContext ec)
3337 this.eclass = ExprClass.MethodGroup;
3339 if (InstanceExpression != null) {
3340 InstanceExpression = InstanceExpression.Resolve (ec);
3341 if (InstanceExpression == null)
3348 public void ReportUsageError (ResolveContext ec)
3350 ec.Report.Error (654, loc, "Method `" + DeclaringType + "." +
3351 Name + "()' is referenced without parentheses");
3354 override public void Emit (EmitContext ec)
3356 throw new NotSupportedException ();
3357 // ReportUsageError ();
3360 public void EmitCall (EmitContext ec, Arguments arguments)
3362 Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);
3365 void Error_AmbiguousCall (ResolveContext ec, MethodSpec ambiguous)
3367 if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ec, ambiguous))
3370 ec.Report.SymbolRelatedToPreviousError (best_candidate);
3371 ec.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
3372 best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ());
3375 protected virtual void Error_InvalidArguments (ResolveContext ec, Location loc, int idx, MethodSpec method,
3376 Argument a, AParametersCollection expected_par, TypeSpec paramType)
3378 ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr;
3380 if (a is CollectionElementInitializer.ElementInitializerArgument) {
3381 ec.Report.SymbolRelatedToPreviousError (method);
3382 if ((expected_par.FixedParameters [idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
3383 ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
3384 TypeManager.CSharpSignature (method));
3387 ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
3388 TypeManager.CSharpSignature (method));
3389 } else if (TypeManager.IsDelegateType (method.DeclaringType)) {
3390 ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
3391 TypeManager.CSharpName (method.DeclaringType));
3393 ec.Report.SymbolRelatedToPreviousError (method);
3395 ec.Report.Error (1928, loc,
3396 "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments",
3397 emg.ExtensionExpression.GetSignatureForError (),
3398 emg.Name, TypeManager.CSharpSignature (method));
3400 ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
3401 TypeManager.CSharpSignature (method));
3405 Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters [idx].ModFlags;
3407 string index = (idx + 1).ToString ();
3408 if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^
3409 (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) {
3410 if ((mod & Parameter.Modifier.ISBYREF) == 0)
3411 ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier",
3412 index, Parameter.GetModifierSignature (a.Modifier));
3414 ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier",
3415 index, Parameter.GetModifierSignature (mod));
3417 string p1 = a.GetSignatureForError ();
3418 string p2 = TypeManager.CSharpName (paramType);
3421 ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
3422 ec.Report.SymbolRelatedToPreviousError (a.Expr.Type);
3423 ec.Report.SymbolRelatedToPreviousError (paramType);
3426 if (idx == 0 && emg != null) {
3427 ec.Report.Error (1929, loc,
3428 "Extension method instance type `{0}' cannot be converted to `{1}'", p1, p2);
3430 ec.Report.Error (1503, loc,
3431 "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2);
3436 public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
3438 ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method",
3439 Name, TypeManager.CSharpName (target));
3442 void Error_ArgumentCountWrong (ResolveContext ec, int arg_count)
3444 ec.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments",
3445 Name, arg_count.ToString ());
3448 protected virtual int GetApplicableParametersCount (MethodSpec method, AParametersCollection parameters)
3450 return parameters.Count;
3453 protected virtual IList<MemberSpec> GetBaseTypeMethods (ResolveContext rc, TypeSpec type)
3455 var arity = type_arguments == null ? -1 : type_arguments.Count;
3456 return TypeManager.MemberLookup (rc.CurrentType, null, type,
3457 MemberKind.Method, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides,
3461 bool GetBaseTypeMethods (ResolveContext rc)
3463 var base_type = Methods.First ().DeclaringType.BaseType;
3464 if (base_type == null)
3467 var methods = GetBaseTypeMethods (rc, base_type);
3468 if (methods == null)
3476 /// Determines if the candidate method is applicable (section 14.4.2.1)
3477 /// to the given set of arguments
3478 /// A return value rates candidate method compatibility,
3479 /// 0 = the best, int.MaxValue = the worst
3481 public int IsApplicable (ResolveContext ec,
3482 ref Arguments arguments, int arg_count, ref MethodSpec method, ref bool params_expanded_form)
3484 var candidate = method;
3486 AParametersCollection pd = candidate.Parameters;
3487 int param_count = GetApplicableParametersCount (candidate, pd);
3488 int optional_count = 0;
3490 if (arg_count != param_count) {
3491 for (int i = 0; i < pd.Count; ++i) {
3492 if (pd.FixedParameters [i].HasDefaultValue) {
3493 optional_count = pd.Count - i;
3498 int args_gap = System.Math.Abs (arg_count - param_count);
3499 if (optional_count != 0) {
3500 if (args_gap > optional_count)
3501 return int.MaxValue - 10000 + args_gap - optional_count;
3503 // Readjust expected number when params used
3506 if (arg_count < param_count)
3508 } else if (arg_count > param_count) {
3509 return int.MaxValue - 10000 + args_gap;
3511 } else if (arg_count != param_count) {
3513 return int.MaxValue - 10000 + args_gap;
3514 if (arg_count < param_count - 1)
3515 return int.MaxValue - 10000 + args_gap;
3518 // Initialize expanded form of a method with 1 params parameter
3519 params_expanded_form = param_count == 1 && pd.HasParams;
3521 // Resize to fit optional arguments
3522 if (optional_count != 0) {
3524 if (arguments == null) {
3525 resized = new Arguments (optional_count);
3527 resized = new Arguments (param_count);
3528 resized.AddRange (arguments);
3531 for (int i = arg_count; i < param_count; ++i)
3533 arguments = resized;
3537 if (arg_count > 0) {
3539 // Shuffle named arguments to the right positions if there are any
3541 if (arguments [arg_count - 1] is NamedArgument) {
3542 arg_count = arguments.Count;
3544 for (int i = 0; i < arg_count; ++i) {
3545 bool arg_moved = false;
3547 NamedArgument na = arguments[i] as NamedArgument;
3551 int index = pd.GetParameterIndexByName (na.Name);
3553 // Named parameter not found or already reordered
3557 // When using parameters which should not be available to the user
3558 if (index >= param_count)
3562 arguments.MarkReorderedArgument (na);
3566 Argument temp = arguments[index];
3567 arguments[index] = arguments[i];
3568 arguments[i] = temp;
3575 arg_count = arguments.Count;
3577 } else if (arguments != null) {
3578 arg_count = arguments.Count;
3582 // 1. Handle generic method using type arguments when specified or type inference
3584 if (candidate.IsGeneric) {
3585 if (type_arguments != null) {
3586 var g_args_count = candidate.Arity;
3587 if (g_args_count != type_arguments.Count)
3588 return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count);
3590 method = candidate.MakeGenericMethod (type_arguments.Arguments);
3592 pd = candidate.Parameters;
3594 int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
3596 return score - 20000;
3598 pd = candidate.Parameters;
3601 if (type_arguments != null)
3602 return int.MaxValue - 15000;
3606 // 2. Each argument has to be implicitly convertible to method parameter
3609 Parameter.Modifier p_mod = 0;
3611 for (int i = 0; i < arg_count; i++) {
3612 Argument a = arguments [i];
3614 if (!pd.FixedParameters [i].HasDefaultValue)
3615 throw new InternalErrorException ();
3617 Expression e = pd.FixedParameters [i].DefaultValue as Constant;
3619 e = new DefaultValueExpression (new TypeExpression (pd.Types [i], loc), loc).Resolve (ec);
3621 arguments [i] = new Argument (e, Argument.AType.Default);
3625 if (p_mod != Parameter.Modifier.PARAMS) {
3626 p_mod = pd.FixedParameters [i].ModFlags & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
3629 params_expanded_form = true;
3632 Parameter.Modifier a_mod = a.Modifier & ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
3634 if (!params_expanded_form)
3635 score = IsArgumentCompatible (ec, a_mod, a, p_mod & ~Parameter.Modifier.PARAMS, pt);
3637 if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && delegate_type == null) {
3638 // It can be applicable in expanded form
3639 score = IsArgumentCompatible (ec, a_mod, a, 0, TypeManager.GetElementType (pt));
3641 params_expanded_form = true;
3645 if (params_expanded_form)
3647 return (arg_count - i) * 2 + score;
3651 if (arg_count != param_count)
3652 params_expanded_form = true;
3657 int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter)
3660 // Types have to be identical when ref or out modifer is used
3662 if (arg_mod != 0 || param_mod != 0) {
3663 if (TypeManager.HasElementType (parameter))
3664 parameter = TypeManager.GetElementType (parameter);
3666 TypeSpec a_type = argument.Type;
3667 if (TypeManager.HasElementType (a_type))
3668 a_type = TypeManager.GetElementType (a_type);
3670 if (a_type != parameter) {
3671 if (a_type == InternalType.Dynamic)
3677 if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) {
3678 if (argument.Type == InternalType.Dynamic)
3685 if (arg_mod != param_mod)
3691 public static MethodGroupExpr MakeUnionSet (MethodGroupExpr mg1, MethodGroupExpr mg2, Location loc)
3702 var all = new List<MemberSpec> (mg1.Methods);
3703 foreach (MethodSpec m in mg2.Methods){
3704 if (!TypeManager.ArrayContainsMethod (all, m, false))
3708 return new MethodGroupExpr (all, null, loc);
3711 static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q)
3713 if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
3715 if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
3718 var ac_p = p as ArrayContainer;
3720 var ac_q = ((ArrayContainer) q);
3721 TypeSpec specific = MoreSpecific (ac_p.Element, (ac_q.Element));
3722 if (specific == ac_p.Element)
3724 if (specific == ac_q.Element)
3726 } else if (TypeManager.IsGenericType (p)) {
3727 var pargs = TypeManager.GetTypeArguments (p);
3728 var qargs = TypeManager.GetTypeArguments (q);
3730 bool p_specific_at_least_once = false;
3731 bool q_specific_at_least_once = false;
3733 for (int i = 0; i < pargs.Length; i++) {
3734 TypeSpec specific = MoreSpecific (pargs[i], qargs[i]);
3735 if (specific == pargs[i])
3736 p_specific_at_least_once = true;
3737 if (specific == qargs[i])
3738 q_specific_at_least_once = true;
3741 if (p_specific_at_least_once && !q_specific_at_least_once)
3743 if (!p_specific_at_least_once && q_specific_at_least_once)
3751 /// Find the Applicable Function Members (7.4.2.1)
3753 /// me: Method Group expression with the members to select.
3754 /// it might contain constructors or methods (or anything
3755 /// that maps to a method).
3757 /// Arguments: ArrayList containing resolved Argument objects.
3759 /// loc: The location if we want an error to be reported, or a Null
3760 /// location for "probing" purposes.
3762 /// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
3763 /// that is the best match of me on Arguments.
3766 public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
3767 bool may_fail, Location loc)
3769 var candidates = new List<MethodSpec> (2);
3770 List<MethodSpec> params_candidates = null;
3772 int arg_count = Arguments != null ? Arguments.Count : 0;
3773 Dictionary<MethodSpec, Arguments> candidates_expanded = null;
3774 Arguments candidate_args = Arguments;
3776 if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
3778 ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
3783 // Enable message recording, it's used mainly by lambda expressions
3785 var msg_recorder = new SessionReportPrinter ();
3786 var prev_recorder = ec.Report.SetPrinter (msg_recorder);
3790 // Methods in a base class are not candidates if any method in a derived
3791 // class is applicable
3793 int best_candidate_rate = int.MaxValue;
3795 foreach (var member in Methods) {
3796 var m = member as MethodSpec;
3798 // TODO: It's wrong when non-member is before applicable method
3799 // TODO: Should report only when at least 1 from the batch is applicable
3800 if (candidates.Count != 0) {
3801 ec.Report.SymbolRelatedToPreviousError (candidates [0]);
3802 ec.Report.SymbolRelatedToPreviousError (member);
3803 ec.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
3804 candidates[0].GetSignatureForError (), member.GetSignatureForError ());
3810 // Check if candidate is applicable (section 14.4.2.1)
3812 bool params_expanded_form = false;
3813 int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref m, ref params_expanded_form);
3815 if (candidate_rate < best_candidate_rate) {
3816 best_candidate_rate = candidate_rate;
3820 if (params_expanded_form) {
3821 if (params_candidates == null)
3822 params_candidates = new List<MethodSpec> (2);
3823 params_candidates.Add (m);
3826 if (candidate_args != Arguments) {
3827 if (candidates_expanded == null)
3828 candidates_expanded = new Dictionary<MethodSpec, Arguments> (2);
3830 candidates_expanded.Add (m, candidate_args);
3831 candidate_args = Arguments;
3834 if (candidate_rate != 0 || has_inaccessible_candidates_only) {
3835 if (msg_recorder != null)
3836 msg_recorder.EndSession ();
3840 msg_recorder = null;
3843 } while (candidates.Count == 0 && GetBaseTypeMethods (ec));
3845 ec.Report.SetPrinter (prev_recorder);
3846 if (msg_recorder != null && !msg_recorder.IsEmpty) {
3848 msg_recorder.Merge (prev_recorder);
3853 int candidate_top = candidates.Count;
3854 if (candidate_top == 0) {
3856 // When we found a top level method which does not match and it's
3857 // not an extension method. We start extension methods lookup from here
3859 if (InstanceExpression != null) {
3860 var first = Methods.First ();
3861 var arity = type_arguments == null ? -1 : type_arguments.Count;
3862 ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, first.Name, arity, loc);
3863 if (ex_method_lookup != null) {
3864 ex_method_lookup.ExtensionExpression = InstanceExpression;
3865 ex_method_lookup.SetTypeArguments (ec, type_arguments);
3866 return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
3874 // Okay so we have failed to find exact match so we
3875 // return error info about the closest match
3877 if (best_candidate != null) {
3878 if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
3881 bool params_expanded = params_candidates != null && params_candidates.Contains (best_candidate);
3882 if (NoExactMatch (ec, ref Arguments, params_expanded))
3887 // We failed to find any method with correct argument count
3889 if (Methods.First ().Kind == MemberKind.Constructor) {
3890 ec.Report.SymbolRelatedToPreviousError (queried_type);
3891 ec.Report.Error (1729, loc,
3892 "The type `{0}' does not contain a constructor that takes `{1}' arguments",
3893 TypeManager.CSharpName (queried_type), arg_count.ToString ());
3895 Error_ArgumentCountWrong (ec, arg_count);
3901 if (arg_count != 0 && Arguments.HasDynamic) {
3902 best_candidate = null;
3907 // Now we actually find the best method
3909 best_candidate = candidates [0];
3910 bool method_params = params_candidates != null && params_candidates.Contains (best_candidate);
3912 for (int ix = 1; ix < candidate_top; ix++) {
3913 var candidate = candidates [ix];
3915 if (candidate == best_candidate)
3918 bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
3920 if (candidates_expanded != null && candidates_expanded.ContainsKey (candidate)) {
3921 candidate_args = candidates_expanded[candidate];
3922 arg_count = candidate_args.Count;
3925 if (BetterFunction (ec, candidate_args, arg_count,
3926 candidate, cand_params,
3927 best_candidate, method_params)) {
3928 best_candidate = candidate;
3929 method_params = cand_params;
3932 if (candidate_args != Arguments) {
3933 candidate_args = Arguments;
3934 arg_count = candidate_args != null ? candidate_args.Count : 0;
3938 if (candidates_expanded != null && candidates_expanded.ContainsKey (best_candidate)) {
3939 candidate_args = candidates_expanded[best_candidate];
3940 arg_count = candidate_args.Count;
3944 // Now check that there are no ambiguities i.e the selected method
3945 // should be better than all the others
3947 MethodSpec ambiguous = null;
3948 for (int ix = 1; ix < candidate_top; ix++) {
3949 var candidate = candidates [ix];
3951 if (candidate == best_candidate)
3954 bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
3955 if (!BetterFunction (ec, candidate_args, arg_count,
3956 best_candidate, method_params,
3957 candidate, cand_params))
3960 ec.Report.SymbolRelatedToPreviousError (candidate);
3961 ambiguous = candidate;
3965 if (ambiguous != null) {
3966 Error_AmbiguousCall (ec, ambiguous);
3971 // And now check if the arguments are all
3972 // compatible, perform conversions if
3973 // necessary etc. and return if everything is
3976 if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
3977 method_params, may_fail, loc))
3980 if (best_candidate == null)
3983 if (best_candidate.IsGeneric) {
3984 ConstraintChecker.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
3985 best_candidate.Constraints, loc, ec.Report);
3989 // Check ObsoleteAttribute on the best method
3991 ObsoleteAttribute oa = best_candidate.GetAttributeObsolete ();
3992 if (oa != null && !ec.IsObsolete)
3993 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
3995 best_candidate.MemberDefinition.SetIsUsed ();
3997 Arguments = candidate_args;
4001 bool NoExactMatch (ResolveContext ec, ref Arguments Arguments, bool params_expanded)
4003 AParametersCollection pd = best_candidate.Parameters;
4004 int arg_count = Arguments == null ? 0 : Arguments.Count;
4006 if (arg_count == pd.Count || pd.HasParams) {
4007 if (best_candidate.IsGeneric) {
4008 if (type_arguments == null) {
4009 ec.Report.Error (411, loc,
4010 "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly",
4011 best_candidate.GetGenericMethodDefinition().GetSignatureForError ());
4016 var ta = type_arguments == null ? 0 : type_arguments.Count;
4017 if (ta != best_candidate.Arity) {
4018 Error_TypeArgumentsCannotBeUsed (ec.Report, loc, best_candidate, type_arguments.Count);
4022 if (has_inaccessible_candidates_only) {
4023 if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
4024 // Although a derived class can access protected members of
4025 // its base class it cannot do so through an instance of the
4026 // base class (CS1540). If the qualifier_type is a base of the
4027 // ec.CurrentType and the lookup succeeds with the latter one,
4028 // then we are in this situation.
4029 Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
4031 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4032 ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
4036 if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, params_expanded, false, loc))
4039 if (has_inaccessible_candidates_only)
4046 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
4048 type_arguments = ta;
4051 public bool VerifyArgumentsCompat (ResolveContext ec, ref Arguments arguments,
4052 int arg_count, MethodSpec method,
4053 bool chose_params_expanded,
4054 bool may_fail, Location loc)
4056 AParametersCollection pd = method.Parameters;
4057 int param_count = GetApplicableParametersCount (method, pd);
4059 int errors = ec.Report.Errors;
4060 Parameter.Modifier p_mod = 0;
4062 int a_idx = 0, a_pos = 0;
4064 ArrayInitializer params_initializers = null;
4065 bool has_unsafe_arg = method.ReturnType.IsPointer;
4067 for (; a_idx < arg_count; a_idx++, ++a_pos) {
4068 a = arguments [a_idx];
4069 if (p_mod != Parameter.Modifier.PARAMS) {
4070 p_mod = pd.FixedParameters [a_idx].ModFlags;
4071 pt = pd.Types [a_idx];
4072 has_unsafe_arg |= pt.IsPointer;
4074 if (p_mod == Parameter.Modifier.PARAMS) {
4075 if (chose_params_expanded) {
4076 params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location);
4077 pt = TypeManager.GetElementType (pt);
4083 // Types have to be identical when ref or out modifer is used
4085 if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) {
4086 if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier)
4089 if (!TypeManager.IsEqual (a.Expr.Type, pt))
4094 NamedArgument na = a as NamedArgument;
4096 int name_index = pd.GetParameterIndexByName (na.Name);
4097 if (name_index < 0 || name_index >= param_count) {
4098 if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) {
4099 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4100 ec.Report.Error (1746, na.Location,
4101 "The delegate `{0}' does not contain a parameter named `{1}'",
4102 TypeManager.CSharpName (DeclaringType), na.Name);
4104 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4105 ec.Report.Error (1739, na.Location,
4106 "The best overloaded method match for `{0}' does not contain a parameter named `{1}'",
4107 TypeManager.CSharpSignature (method), na.Name);
4109 } else if (arguments[name_index] != a) {
4110 if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType))
4111 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4113 ec.Report.SymbolRelatedToPreviousError (best_candidate);
4115 ec.Report.Error (1744, na.Location,
4116 "Named argument `{0}' cannot be used for a parameter which has positional argument specified",
4122 if (a.Expr.Type == InternalType.Dynamic)
4125 if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt))
4128 Expression conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc);
4133 // Convert params arguments to an array initializer
4135 if (params_initializers != null) {
4136 // we choose to use 'a.Expr' rather than 'conv' so that
4137 // we don't hide the kind of expression we have (esp. CompoundAssign.Helper)
4138 params_initializers.Add (a.Expr);
4139 arguments.RemoveAt (a_idx--);
4144 // Update the argument with the implicit conversion
4148 if (a_idx != arg_count) {
4149 if (!may_fail && ec.Report.Errors == errors) {
4150 if (CustomErrorHandler != null)
4151 CustomErrorHandler.NoExactMatch (ec, best_candidate);
4153 Error_InvalidArguments (ec, loc, a_pos, method, a, pd, pt);
4159 // Fill not provided arguments required by params modifier
4161 if (params_initializers == null && pd.HasParams && arg_count + 1 == param_count) {
4162 if (arguments == null)
4163 arguments = new Arguments (1);
4165 pt = pd.Types [param_count - 1];
4166 pt = TypeManager.GetElementType (pt);
4167 has_unsafe_arg |= pt.IsPointer;
4168 params_initializers = new ArrayInitializer (0, loc);
4172 // Append an array argument with all params arguments
4174 if (params_initializers != null) {
4175 arguments.Add (new Argument (
4176 new ArrayCreation (new TypeExpression (pt, loc), "[]", params_initializers, loc).Resolve (ec)));
4180 if (arg_count < param_count) {
4182 Error_ArgumentCountWrong (ec, arg_count);
4186 if (has_unsafe_arg && !ec.IsUnsafe) {
4188 UnsafeError (ec, loc);
4196 public class ConstantExpr : MemberExpr
4200 public ConstantExpr (ConstSpec constant, Location loc)
4202 this.constant = constant;
4206 public override string Name {
4207 get { throw new NotImplementedException (); }
4210 public override bool IsInstance {
4211 get { return !IsStatic; }
4214 public override bool IsStatic {
4215 get { return true; }
4218 public override TypeSpec DeclaringType {
4219 get { return constant.DeclaringType; }
4222 public override Expression CreateExpressionTree (ResolveContext ec)
4224 throw new NotSupportedException ("ET");
4227 protected override Expression DoResolve (ResolveContext rc)
4229 constant.MemberDefinition.SetIsUsed ();
4231 if (!rc.IsObsolete) {
4232 var oa = constant.GetAttributeObsolete ();
4234 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (constant), loc, rc.Report);
4237 // Constants are resolved on-demand
4238 var c = constant.Value.Resolve (rc) as Constant;
4240 // Creates reference expression to the constant value
4241 return Constant.CreateConstant (rc, constant.MemberType, c.GetValue (), loc);
4244 public override void Emit (EmitContext ec)
4246 throw new NotSupportedException ();
4249 public override string GetSignatureForError ()
4251 return TypeManager.GetFullNameSignature (constant);
4256 /// Fully resolved expression that evaluates to a Field
4258 public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference {
4259 protected FieldSpec spec;
4260 VariableInfo variable_info;
4262 LocalTemporary temp;
4265 protected FieldExpr (Location l)
4270 public FieldExpr (FieldSpec spec, Location loc)
4275 type = spec.MemberType;
4278 public FieldExpr (FieldBase fi, Location l)
4283 public override string Name {
4289 public override bool IsInstance {
4291 return !spec.IsStatic;
4295 public override bool IsStatic {
4297 return spec.IsStatic;
4301 public FieldSpec Spec {
4307 public override TypeSpec DeclaringType {
4309 return spec.DeclaringType;
4313 public override string GetSignatureForError ()
4315 return TypeManager.GetFullNameSignature (spec);
4318 public VariableInfo VariableInfo {
4320 return variable_info;
4324 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
4325 SimpleName original)
4327 if (spec.MemberType.IsPointer && !ec.IsUnsafe) {
4328 UnsafeError (ec, loc);
4331 return base.ResolveMemberAccess (ec, left, loc, original);
4334 public void SetHasAddressTaken ()
4336 IVariableReference vr = InstanceExpression as IVariableReference;
4338 vr.SetHasAddressTaken ();
4341 public override Expression CreateExpressionTree (ResolveContext ec)
4343 Expression instance;
4344 if (InstanceExpression == null) {
4345 instance = new NullLiteral (loc);
4347 instance = InstanceExpression.CreateExpressionTree (ec);
4350 Arguments args = Arguments.CreateForExpressionTree (ec, null,
4352 CreateTypeOfExpression ());
4354 return CreateExpressionFactoryCall (ec, "Field", args);
4357 public Expression CreateTypeOfExpression ()
4359 return new TypeOfField (spec, loc);
4362 protected override Expression DoResolve (ResolveContext ec)
4364 return DoResolve (ec, false, false);
4367 Expression DoResolve (ResolveContext ec, bool lvalue_instance, bool out_access)
4370 if (InstanceExpression == null){
4372 // This can happen when referencing an instance field using
4373 // a fully qualified type expression: TypeName.InstanceField = xxx
4375 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
4379 // Resolve the field's instance expression while flow analysis is turned
4380 // off: when accessing a field "a.b", we must check whether the field
4381 // "a.b" is initialized, not whether the whole struct "a" is initialized.
4383 if (lvalue_instance) {
4384 using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
4385 Expression right_side =
4386 out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
4388 if (InstanceExpression != EmptyExpression.Null)
4389 InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
4392 if (InstanceExpression != EmptyExpression.Null) {
4393 using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
4394 InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
4399 if (InstanceExpression == null)
4402 using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
4403 InstanceExpression.CheckMarshalByRefAccess (ec);
4407 if (!ec.IsObsolete) {
4408 ObsoleteAttribute oa = spec.GetAttributeObsolete ();
4410 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (spec), loc, ec.Report);
4413 var fb = spec as FixedFieldSpec;
4414 IVariableReference var = InstanceExpression as IVariableReference;
4417 IFixedExpression fe = InstanceExpression as IFixedExpression;
4418 if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
4419 ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
4422 if (InstanceExpression.eclass != ExprClass.Variable) {
4423 ec.Report.SymbolRelatedToPreviousError (spec);
4424 ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
4425 TypeManager.GetFullNameSignature (spec));
4426 } else if (var != null && var.IsHoisted) {
4427 AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc);
4430 return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
4433 eclass = ExprClass.Variable;
4435 // If the instance expression is a local variable or parameter.
4436 if (var == null || var.VariableInfo == null)
4439 VariableInfo vi = var.VariableInfo;
4440 if (!vi.IsFieldAssigned (ec, Name, loc))
4443 variable_info = vi.GetSubStruct (Name);
4447 static readonly int [] codes = {
4448 191, // instance, write access
4449 192, // instance, out access
4450 198, // static, write access
4451 199, // static, out access
4452 1648, // member of value instance, write access
4453 1649, // member of value instance, out access
4454 1650, // member of value static, write access
4455 1651 // member of value static, out access
4458 static readonly string [] msgs = {
4459 /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)",
4460 /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)",
4461 /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
4462 /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)",
4463 /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
4464 /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
4465 /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",
4466 /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)"
4469 // The return value is always null. Returning a value simplifies calling code.
4470 Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side)
4473 if (right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess)
4477 if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess)
4479 ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ());
4484 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
4486 IVariableReference var = InstanceExpression as IVariableReference;
4487 if (var != null && var.VariableInfo != null)
4488 var.VariableInfo.SetFieldAssigned (ec, Name);
4490 bool lvalue_instance = !spec.IsStatic && TypeManager.IsValueType (spec.DeclaringType);
4491 bool out_access = right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess;
4493 Expression e = DoResolve (ec, lvalue_instance, out_access);
4498 spec.MemberDefinition.SetIsAssigned ();
4500 if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess.Instance) &&
4501 (spec.Modifiers & Modifiers.VOLATILE) != 0) {
4502 ec.Report.Warning (420, 1, loc,
4503 "`{0}': A volatile field references will not be treated as volatile",
4504 spec.GetSignatureForError ());
4507 if (spec.IsReadOnly) {
4508 // InitOnly fields can only be assigned in constructors or initializers
4509 if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope))
4510 return Report_AssignToReadonly (ec, right_side);
4512 if (ec.HasSet (ResolveContext.Options.ConstructorScope)) {
4514 // InitOnly fields cannot be assigned-to in a different constructor from their declaring type
4515 if (!TypeManager.IsEqual (ec.CurrentMemberDefinition.Parent.Definition, DeclaringType.GetDefinition ()))
4516 return Report_AssignToReadonly (ec, right_side);
4517 // static InitOnly fields cannot be assigned-to in an instance constructor
4518 if (IsStatic && !ec.IsStatic)
4519 return Report_AssignToReadonly (ec, right_side);
4520 // instance constructors can't modify InitOnly fields of other instances of the same type
4521 if (!IsStatic && !(InstanceExpression is This))
4522 return Report_AssignToReadonly (ec, right_side);
4526 if (right_side == EmptyExpression.OutAccess.Instance &&
4527 !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) {
4528 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4529 ec.Report.Warning (197, 1, loc,
4530 "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",
4531 GetSignatureForError ());
4534 eclass = ExprClass.Variable;
4538 bool is_marshal_by_ref ()
4540 return !IsStatic && TypeManager.IsStruct (Type) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type);
4543 public override void CheckMarshalByRefAccess (ResolveContext ec)
4545 if (is_marshal_by_ref () && !(InstanceExpression is This)) {
4546 ec.Report.SymbolRelatedToPreviousError (DeclaringType);
4547 ec.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",
4548 GetSignatureForError ());
4552 public override int GetHashCode ()
4554 return spec.GetHashCode ();
4557 public bool IsFixed {
4560 // A variable of the form V.I is fixed when V is a fixed variable of a struct type
4562 IVariableReference variable = InstanceExpression as IVariableReference;
4563 if (variable != null)
4564 return InstanceExpression.Type.IsStruct && variable.IsFixed;
4566 IFixedExpression fe = InstanceExpression as IFixedExpression;
4567 return fe != null && fe.IsFixed;
4571 public bool IsHoisted {
4573 IVariableReference hv = InstanceExpression as IVariableReference;
4574 return hv != null && hv.IsHoisted;
4578 public override bool Equals (object obj)
4580 FieldExpr fe = obj as FieldExpr;
4584 if (spec != fe.spec)
4587 if (InstanceExpression == null || fe.InstanceExpression == null)
4590 return InstanceExpression.Equals (fe.InstanceExpression);
4593 public void Emit (EmitContext ec, bool leave_copy)
4595 bool is_volatile = false;
4597 if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
4600 spec.MemberDefinition.SetIsUsed ();
4604 ec.Emit (OpCodes.Volatile);
4606 ec.Emit (OpCodes.Ldsfld, spec);
4609 EmitInstance (ec, false);
4611 // Optimization for build-in types
4612 if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType) && TypeManager.IsEqual (InstanceExpression.Type, type)) {
4613 ec.EmitLoadFromPtr (type);
4615 var ff = spec as FixedFieldSpec;
4617 ec.Emit (OpCodes.Ldflda, spec);
4618 ec.Emit (OpCodes.Ldflda, ff.Element);
4621 ec.Emit (OpCodes.Volatile);
4623 ec.Emit (OpCodes.Ldfld, spec);
4629 ec.Emit (OpCodes.Dup);
4631 temp = new LocalTemporary (this.Type);
4637 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
4639 prepared = prepare_for_load;
4640 EmitInstance (ec, prepared);
4644 ec.Emit (OpCodes.Dup);
4646 temp = new LocalTemporary (this.Type);
4651 if ((spec.Modifiers & Modifiers.VOLATILE) != 0)
4652 ec.Emit (OpCodes.Volatile);
4654 spec.MemberDefinition.SetIsAssigned ();
4657 ec.Emit (OpCodes.Stsfld, spec);
4659 ec.Emit (OpCodes.Stfld, spec);
4668 public override void Emit (EmitContext ec)
4673 public override void EmitSideEffect (EmitContext ec)
4675 bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0;
4677 if (is_volatile || is_marshal_by_ref ())
4678 base.EmitSideEffect (ec);
4681 public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name)
4684 "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'",
4685 name, GetSignatureForError ());
4688 public void AddressOf (EmitContext ec, AddressOp mode)
4690 if ((mode & AddressOp.Store) != 0)
4691 spec.MemberDefinition.SetIsAssigned ();
4692 if ((mode & AddressOp.Load) != 0)
4693 spec.MemberDefinition.SetIsUsed ();
4696 // Handle initonly fields specially: make a copy and then
4697 // get the address of the copy.
4700 if (spec.IsReadOnly){
4702 if (ec.HasSet (EmitContext.Options.ConstructorScope)){
4715 local = ec.DeclareLocal (type, false);
4716 ec.Emit (OpCodes.Stloc, local);
4717 ec.Emit (OpCodes.Ldloca, local);
4723 ec.Emit (OpCodes.Ldsflda, spec);
4726 EmitInstance (ec, false);
4727 ec.Emit (OpCodes.Ldflda, spec);
4731 public SLE.Expression MakeAssignExpression (BuilderContext ctx)
4733 return MakeExpression (ctx);
4736 public override SLE.Expression MakeExpression (BuilderContext ctx)
4738 return SLE.Expression.Field (InstanceExpression.MakeExpression (ctx), spec.GetMetaInfo ());
4744 /// Expression that evaluates to a Property. The Assign class
4745 /// might set the `Value' expression if we are in an assignment.
4747 /// This is not an LValue because we need to re-write the expression, we
4748 /// can not take data from the stack and store it.
4750 public class PropertyExpr : MemberExpr, IDynamicAssign
4753 TypeArguments targs;
4755 LocalTemporary temp;
4758 public PropertyExpr (TypeSpec container_type, PropertySpec spec, Location l)
4763 type = spec.MemberType;
4768 public override string Name {
4774 public override bool IsInstance {
4780 public override bool IsStatic {
4782 return spec.IsStatic;
4788 public override Expression CreateExpressionTree (ResolveContext ec)
4791 if (IsSingleDimensionalArrayLength ()) {
4792 args = new Arguments (1);
4793 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
4794 return CreateExpressionFactoryCall (ec, "ArrayLength", args);
4798 Error_BaseAccessInExpressionTree (ec, loc);
4802 args = new Arguments (2);
4803 if (InstanceExpression == null)
4804 args.Add (new Argument (new NullLiteral (loc)));
4806 args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec)));
4807 args.Add (new Argument (new TypeOfMethod (spec.Get, loc)));
4808 return CreateExpressionFactoryCall (ec, "Property", args);
4811 public Expression CreateSetterTypeOfExpression ()
4813 return new TypeOfMethod (spec.Set, loc);
4816 public override TypeSpec DeclaringType {
4818 return spec.DeclaringType;
4822 public override string GetSignatureForError ()
4824 return TypeManager.GetFullNameSignature (spec);
4827 public SLE.Expression MakeAssignExpression (BuilderContext ctx)
4829 return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) spec.Set.GetMetaInfo ());
4832 public override SLE.Expression MakeExpression (BuilderContext ctx)
4834 return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) spec.Get.GetMetaInfo ());
4837 public PropertySpec PropertyInfo {
4843 bool InstanceResolve (ResolveContext ec, bool lvalue_instance, bool must_do_cs1540_check)
4846 InstanceExpression = null;
4850 if (InstanceExpression == null) {
4851 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
4855 InstanceExpression = InstanceExpression.Resolve (ec);
4856 if (lvalue_instance && InstanceExpression != null)
4857 InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess);
4859 if (InstanceExpression == null)
4862 InstanceExpression.CheckMarshalByRefAccess (ec);
4864 if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) &&
4865 !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
4866 !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
4867 !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
4868 ec.Report.SymbolRelatedToPreviousError (spec);
4869 Error_CannotAccessProtected (ec, loc, spec, InstanceExpression.Type, ec.CurrentType);
4876 void Error_PropertyNotValid (ResolveContext ec)
4878 ec.Report.SymbolRelatedToPreviousError (spec);
4879 ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language",
4880 GetSignatureForError ());
4883 public bool IsAccessibleFrom (TypeSpec invocation_type, bool lvalue)
4886 var accessor = lvalue ? spec.Set : spec.Get;
4887 if (accessor == null && lvalue)
4888 accessor = spec.Get;
4889 return accessor != null && IsMemberAccessible (invocation_type, accessor, out dummy);
4892 bool IsSingleDimensionalArrayLength ()
4894 if (DeclaringType != TypeManager.array_type || !spec.HasGet || Name != "Length")
4897 ArrayContainer ac = InstanceExpression.Type as ArrayContainer;
4898 return ac != null && ac.Rank == 1;
4901 protected override Expression DoResolve (ResolveContext ec)
4903 eclass = ExprClass.PropertyAccess;
4905 bool must_do_cs1540_check = false;
4906 ec.Report.DisableReporting ();
4907 bool res = ResolveGetter (ec, ref must_do_cs1540_check);
4908 ec.Report.EnableReporting ();
4911 if (InstanceExpression != null) {
4912 TypeSpec expr_type = InstanceExpression.Type;
4913 ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, 0, loc);
4914 if (ex_method_lookup != null) {
4915 ex_method_lookup.ExtensionExpression = InstanceExpression;
4916 ex_method_lookup.SetTypeArguments (ec, targs);
4917 return ex_method_lookup.Resolve (ec);
4921 ResolveGetter (ec, ref must_do_cs1540_check);
4925 if (!InstanceResolve (ec, false, must_do_cs1540_check))
4929 // Only base will allow this invocation to happen.
4931 if (IsBase && spec.IsAbstract) {
4932 Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (spec));
4935 if (spec.MemberType.IsPointer && !ec.IsUnsafe){
4936 UnsafeError (ec, loc);
4939 if (!ec.IsObsolete) {
4940 ObsoleteAttribute oa = spec.GetAttributeObsolete ();
4942 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
4948 override public Expression DoResolveLValue (ResolveContext ec, Expression right_side)
4950 eclass = ExprClass.PropertyAccess;
4952 if (right_side == EmptyExpression.OutAccess.Instance) {
4953 if (ec.CurrentBlock.Toplevel.GetParameterReference (spec.Name, loc) is MemberAccess) {
4954 ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
4957 right_side.DoResolveLValue (ec, this);
4962 if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) {
4963 Error_CannotModifyIntermediateExpressionValue (ec);
4966 if (spec.IsNotRealProperty) {
4967 Error_PropertyNotValid (ec);
4972 if (ec.CurrentBlock.Toplevel.GetParameterReference (spec.Name, loc) is MemberAccess) {
4973 ec.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value",
4976 ec.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)",
4977 GetSignatureForError ());
4982 if (targs != null) {
4983 base.SetTypeArguments (ec, targs);
4987 bool must_do_cs1540_check;
4988 if (!IsMemberAccessible (ec.CurrentType, spec.Set, out must_do_cs1540_check)) {
4989 if (spec.HasDifferentAccessibility) {
4990 ec.Report.SymbolRelatedToPreviousError (spec.Set);
4991 ec.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible",
4992 TypeManager.CSharpSignature (spec));
4994 ec.Report.SymbolRelatedToPreviousError (spec.Set);
4995 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec.Set), ec.Report);
5000 if (!InstanceResolve (ec, TypeManager.IsStruct (spec.DeclaringType), must_do_cs1540_check))
5004 // Only base will allow this invocation to happen.
5006 if (IsBase && spec.IsAbstract){
5007 Error_CannotCallAbstractBase (ec, TypeManager.GetFullNameSignature (spec));
5010 if (spec.MemberType.IsPointer && !ec.IsUnsafe) {
5011 UnsafeError (ec, loc);
5014 if (!ec.IsObsolete) {
5015 ObsoleteAttribute oa = spec.GetAttributeObsolete ();
5017 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5023 public override void Emit (EmitContext ec)
5028 public void Emit (EmitContext ec, bool leave_copy)
5031 // Special case: length of single dimension array property is turned into ldlen
5033 if (IsSingleDimensionalArrayLength ()) {
5035 EmitInstance (ec, false);
5036 ec.Emit (OpCodes.Ldlen);
5037 ec.Emit (OpCodes.Conv_I4);
5041 Invocation.EmitCall (ec, IsBase, InstanceExpression, spec.Get, null, loc, prepared, false);
5044 ec.Emit (OpCodes.Dup);
5046 temp = new LocalTemporary (this.Type);
5053 // Implements the IAssignMethod interface for assignments
5055 public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
5057 Expression my_source = source;
5059 if (prepare_for_load) {
5064 ec.Emit (OpCodes.Dup);
5066 temp = new LocalTemporary (this.Type);
5070 } else if (leave_copy) {
5072 temp = new LocalTemporary (this.Type);
5077 Arguments args = new Arguments (1);
5078 args.Add (new Argument (my_source));
5080 Invocation.EmitCall (ec, IsBase, InstanceExpression, spec.Set, args, loc, false, prepared);
5088 bool ResolveGetter (ResolveContext ec, ref bool must_do_cs1540_check)
5090 if (targs != null) {
5091 base.SetTypeArguments (ec, targs);
5095 if (spec.IsNotRealProperty) {
5096 Error_PropertyNotValid (ec);
5101 if (InstanceExpression != EmptyExpression.Null) {
5102 ec.Report.SymbolRelatedToPreviousError (spec);
5103 ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor",
5104 spec.GetSignatureForError ());
5109 if (spec.HasGet && !IsMemberAccessible (ec.CurrentType, spec.Get, out must_do_cs1540_check)) {
5110 if (spec.HasDifferentAccessibility) {
5111 ec.Report.SymbolRelatedToPreviousError (spec.Get);
5112 ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible",
5113 TypeManager.CSharpSignature (spec));
5115 ec.Report.SymbolRelatedToPreviousError (spec.Get);
5116 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec.Get), ec.Report);
5125 public override void SetTypeArguments (ResolveContext ec, TypeArguments ta)
5132 /// Fully resolved expression that evaluates to an Event
5134 public class EventExpr : MemberExpr
5136 readonly EventSpec spec;
5138 public EventExpr (EventSpec spec, Location loc)
5144 public override string Name {
5150 public override bool IsInstance {
5152 return !spec.IsStatic;
5156 public override bool IsStatic {
5158 return spec.IsStatic;
5162 public override TypeSpec DeclaringType {
5164 return spec.DeclaringType;
5168 public void Error_AssignmentEventOnly (ResolveContext ec)
5170 ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator",
5171 GetSignatureForError ());
5174 public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, Location loc,
5175 SimpleName original)
5178 // If the event is local to this class, we transform ourselves into a FieldExpr
5181 if (spec.DeclaringType == ec.CurrentType ||
5182 TypeManager.IsNestedChildOf(ec.CurrentType, spec.DeclaringType)) {
5184 // TODO: Breaks dynamic binder as currect context fields are imported and not compiled
5185 EventField mi = spec.MemberDefinition as EventField;
5187 if (mi != null && mi.HasBackingField) {
5190 mi.CheckObsoleteness (loc);
5192 if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
5193 Error_AssignmentEventOnly (ec);
5195 FieldExpr ml = new FieldExpr (mi.BackingField, loc);
5197 InstanceExpression = null;
5199 return ml.ResolveMemberAccess (ec, left, loc, original);
5203 if (left is This && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope))
5204 Error_AssignmentEventOnly (ec);
5206 return base.ResolveMemberAccess (ec, left, loc, original);
5209 bool InstanceResolve (ResolveContext ec, bool must_do_cs1540_check)
5212 InstanceExpression = null;
5216 if (InstanceExpression == null) {
5217 SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
5221 InstanceExpression = InstanceExpression.Resolve (ec);
5222 if (InstanceExpression == null)
5225 if (IsBase && spec.IsAbstract) {
5226 Error_CannotCallAbstractBase (ec, TypeManager.CSharpSignature(spec));
5231 // This is using the same mechanism as the CS1540 check in PropertyExpr.
5232 // However, in the Event case, we reported a CS0122 instead.
5234 // TODO: Exact copy from PropertyExpr
5236 if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null &&
5237 !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) &&
5238 !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) &&
5239 !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) {
5240 ec.Report.SymbolRelatedToPreviousError (spec);
5241 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report);
5248 public bool IsAccessibleFrom (TypeSpec invocation_type)
5251 return IsMemberAccessible (invocation_type, spec.AccessorAdd, out dummy) &&
5252 IsMemberAccessible (invocation_type, spec.AccessorRemove, out dummy);
5255 public override Expression CreateExpressionTree (ResolveContext ec)
5257 throw new NotSupportedException ("ET");
5260 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5262 // contexts where an LValue is valid have already devolved to FieldExprs
5263 Error_CannotAssign (ec);
5267 protected override Expression DoResolve (ResolveContext ec)
5269 eclass = ExprClass.EventAccess;
5271 bool must_do_cs1540_check;
5272 if (!(IsMemberAccessible (ec.CurrentType, spec.AccessorAdd, out must_do_cs1540_check) &&
5273 IsMemberAccessible (ec.CurrentType, spec.AccessorRemove, out must_do_cs1540_check))) {
5274 ec.Report.SymbolRelatedToPreviousError (spec);
5275 ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report);
5279 if (!InstanceResolve (ec, must_do_cs1540_check))
5282 if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) {
5283 Error_CannotAssign (ec);
5287 if (!ec.IsObsolete) {
5288 var oa = spec.GetAttributeObsolete ();
5290 AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);
5293 spec.MemberDefinition.SetIsUsed ();
5294 type = spec.MemberType;
5299 public override void Emit (EmitContext ec)
5301 throw new NotSupportedException ();
5302 //Error_CannotAssign ();
5305 public void Error_CannotAssign (ResolveContext ec)
5307 ec.Report.Error (70, loc,
5308 "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'",
5309 GetSignatureForError (), TypeManager.CSharpName (spec.DeclaringType));
5312 public override string GetSignatureForError ()
5314 return TypeManager.CSharpSignature (spec);
5317 public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source)
5319 Arguments args = new Arguments (1);
5320 args.Add (new Argument (source));
5321 Invocation.EmitCall (ec, IsBase, InstanceExpression,
5322 is_add ? spec.AccessorAdd : spec.AccessorRemove,
5327 public class TemporaryVariable : VariableReference
5331 public TemporaryVariable (TypeSpec type, Location loc)
5337 public override Expression CreateExpressionTree (ResolveContext ec)
5339 throw new NotSupportedException ("ET");
5342 protected override Expression DoResolve (ResolveContext ec)
5344 eclass = ExprClass.Variable;
5346 TypeExpr te = new TypeExpression (type, loc);
5347 li = ec.CurrentBlock.AddTemporaryVariable (te, loc);
5348 if (!li.Resolve (ec))
5352 // Don't capture temporary variables except when using
5353 // iterator redirection
5355 if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) {
5356 AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec);
5357 storey.CaptureLocalVariable (ec, li);
5363 public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
5365 return Resolve (ec);
5368 public override void Emit (EmitContext ec)
5373 public void EmitAssign (EmitContext ec, Expression source)
5375 EmitAssign (ec, source, false, false);
5378 public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
5380 return li.HoistedVariant;
5383 public override bool IsFixed {
5384 get { return true; }
5387 public override bool IsRef {
5388 get { return false; }
5391 public override string Name {
5392 get { throw new NotImplementedException (); }
5395 public override void SetHasAddressTaken ()
5397 throw new NotImplementedException ();
5400 protected override ILocalVariable Variable {
5404 public override VariableInfo VariableInfo {
5405 get { throw new NotImplementedException (); }
5410 /// Handles `var' contextual keyword; var becomes a keyword only
5411 /// if no type called var exists in a variable scope
5413 class VarExpr : SimpleName
5415 // Used for error reporting only
5416 int initializers_count;
5418 public VarExpr (Location loc)
5421 initializers_count = 1;
5424 public int VariableInitializersCount {
5426 this.initializers_count = value;
5430 public bool InferType (ResolveContext ec, Expression right_side)
5433 throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
5435 type = right_side.Type;
5436 if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) {
5437 ec.Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
5438 right_side.GetSignatureForError ());
5442 eclass = ExprClass.Variable;
5446 protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec)
5448 if (RootContext.Version < LanguageVersion.V_3)
5449 base.Error_TypeOrNamespaceNotFound (ec);
5451 ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
5454 public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent)
5456 TypeExpr te = base.ResolveAsContextualType (rc, true);
5460 if (RootContext.Version < LanguageVersion.V_3)
5461 rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable");
5463 if (initializers_count == 1)
5466 if (initializers_count > 1) {
5467 rc.Compiler.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
5468 initializers_count = 1;
5472 if (initializers_count == 0) {
5473 initializers_count = 1;
5474 rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");