X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=40589398195051b6583e86d352a81839ec3555dd;hb=72e4b412877dbfae80b149c068ed1f0715b2bfe1;hp=400d1f41056ea43d69328672ff281bc2caceb94c;hpb=0bd4004c832f6c5a02c35cada2b6fdbedd1563a2;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 400d1f41056..40589398195 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -10,13 +10,16 @@ // // +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using SLE = System.Linq.Expressions; +using System.Linq; + namespace Mono.CSharp { - using System; - using System.Collections; - using System.Diagnostics; - using System.Reflection; - using System.Reflection.Emit; - using System.Text; /// /// The ExprClass class contains the is used to pass the @@ -25,7 +28,7 @@ namespace Mono.CSharp { /// nothing). /// public enum ExprClass : byte { - Invalid, + Unresolved = 0, Value, Variable, @@ -58,18 +61,6 @@ namespace Mono.CSharp { // Mask of all the expression class flags. MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter, - - // Disable control flow analysis while resolving the expression. - // This is used when resolving the instance expression of a field expression. - DisableFlowAnalysis = 1 << 10, - - // Set if this is resolving the first part of a MemberAccess. - Intermediate = 1 << 11, - - // Disable control flow analysis _of struct_ while resolving the expression. - // This is used when resolving the instance expression of a field expression. - DisableStructFlowAnalysis = 1 << 12, - } // @@ -126,10 +117,10 @@ namespace Mono.CSharp { /// public abstract class Expression { public ExprClass eclass; - protected Type type; + protected TypeSpec type; protected Location loc; - public Type Type { + public TypeSpec Type { get { return type; } set { type = value; } } @@ -138,53 +129,37 @@ namespace Mono.CSharp { get { return loc; } } - /// - /// Utility wrapper routine for Error, just to beautify the code - /// - public void Error (int error, string s) - { - Report.Error (error, loc, s); - } - // Not nice but we have broken hierarchy. - public virtual void CheckMarshalByRefAccess (EmitContext ec) - { - } - - public virtual bool GetAttributableValue (EmitContext ec, Type value_type, out object value) + public virtual void CheckMarshalByRefAccess (ResolveContext ec) { - Attribute.Error_AttributeArgumentNotValid (loc); - value = null; - return false; } public virtual string GetSignatureForError () { - return TypeManager.CSharpName (type); + return type.GetDefinition ().GetSignatureForError (); } - public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check) + public static bool IsMemberAccessible (TypeSpec invocation_type, MemberSpec mi, out bool must_do_cs1540_check) { - MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask; + var ma = mi.Modifiers & Modifiers.AccessibilityMask; must_do_cs1540_check = false; // by default we do not check for this - if (ma == MethodAttributes.Public) + if (ma == Modifiers.PUBLIC) return true; - + // // If only accessible to the current class or children // - if (ma == MethodAttributes.Private) - return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) || + if (ma == Modifiers.PRIVATE) + return invocation_type.MemberDefinition == mi.DeclaringType.MemberDefinition || TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType); - if (TypeManager.IsThisOrFriendAssembly (mi.DeclaringType.Assembly)) { - if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) - return true; - } else { - if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem) - return false; + if ((ma & Modifiers.INTERNAL) != 0) { + var b = TypeManager.IsThisOrFriendAssembly (invocation_type == InternalType.FakeInternalType ? + CodeGen.Assembly.Builder : invocation_type.Assembly, mi.DeclaringType.Assembly); + if (b || ma == Modifiers.INTERNAL) + return b; } // Family and FamANDAssem require that we derive. @@ -231,9 +206,9 @@ namespace Mono.CSharp { /// to a valid type (this is the type of the /// expression). /// - public abstract Expression DoResolve (EmitContext ec); + protected abstract Expression DoResolve (ResolveContext rc); - public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side) + public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side) { return null; } @@ -242,16 +217,15 @@ namespace Mono.CSharp { // This is used if the expression should be resolved as a type or namespace name. // the default implementation fails. // - public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext rc, bool silent) + public virtual FullNamedExpression ResolveAsTypeStep (IMemberContext rc, bool silent) { if (!silent) { - Expression e = this; - EmitContext ec = rc as EmitContext; - if (ec != null) - e = e.Resolve (ec); + ResolveContext ec = new ResolveContext (rc); + Expression e = Resolve (ec); if (e != null) - e.Error_UnexpectedKind (ResolveFlags.Type, loc); + e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc); } + return null; } @@ -259,7 +233,7 @@ namespace Mono.CSharp { // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with // same name exists or as a keyword when no type was found // - public virtual TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent) + public virtual TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent) { return ResolveAsTypeTerminal (rc, silent); } @@ -269,45 +243,9 @@ namespace Mono.CSharp { // value will be returned if the expression is not a type // reference // - public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) - { - TypeExpr te = ResolveAsBaseTerminal (ec, silent); - if (te == null) - return null; - - if (!silent) { // && !(te is TypeParameterExpr)) { - ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type); - if (obsolete_attr != null && !ec.IsInObsoleteScope) { - AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location); - } - } - - GenericTypeExpr ct = te as GenericTypeExpr; - if (ct != null) { - // - // TODO: Constrained type parameters check for parameters of generic method overrides is broken - // There are 2 solutions. - // 1, Skip this check completely when we are in override/explicit impl scope - // 2, Copy type parameters constraints from base implementation and pass (they have to be emitted anyway) - // - MemberCore gm = ec as GenericMethod; - if (gm == null) - gm = ec as Method; - if (gm != null && ((gm.ModFlags & Modifiers.OVERRIDE) != 0 || gm.MemberName.Left != null)) { - te.loc = loc; - return te; - } - - // TODO: silent flag is ignored - ct.CheckConstraints (ec); - } - - return te; - } - - public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent) + public virtual TypeExpr ResolveAsTypeTerminal (IMemberContext ec , bool silent) { - int errors = Report.Errors; + int errors = ec.Compiler.Report.Errors; FullNamedExpression fne = ResolveAsTypeStep (ec, silent); @@ -316,135 +254,172 @@ namespace Mono.CSharp { TypeExpr te = fne as TypeExpr; if (te == null) { - if (!silent && errors == Report.Errors) - fne.Error_UnexpectedKind (null, "type", loc); + if (!silent && errors == ec.Compiler.Report.Errors) + fne.Error_UnexpectedKind (ec.Compiler.Report, null, "type", loc); return null; } - if (!te.CheckAccessLevel (ec.GenericDeclContainer)) { - Report.SymbolRelatedToPreviousError (te.Type); - ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type)); - return null; + if (!te.CheckAccessLevel (ec)) { + ec.Compiler.Report.SymbolRelatedToPreviousError (te.Type); + ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type), ec.Compiler.Report); } te.loc = loc; + + // + // Obsolete checks cannot be done when resolving base context as they + // require type dependecies to be set but we are just resolving them + // + if (!silent && !(ec is TypeContainer.BaseContext)) { + ObsoleteAttribute obsolete_attr = te.Type.GetAttributeObsolete (); + if (obsolete_attr != null && !ec.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, ec.Compiler.Report); + } + } + return te; } - - public static void ErrorIsInaccesible (Location loc, string name) + + public static void ErrorIsInaccesible (Location loc, string name, Report Report) { Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name); } - protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container) + protected static void Error_CannotAccessProtected (ResolveContext ec, Location loc, MemberSpec m, TypeSpec qualifier, TypeSpec container) { - Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'." + ec.Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}'." + " The qualifier must be of type `{2}' or derived from it", - TypeManager.GetFullNameSignature (m), + m.GetSignatureForError (), TypeManager.CSharpName (qualifier), TypeManager.CSharpName (container)); } - public static void Error_InvalidExpressionStatement (Location loc) + public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name) { - Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " + - "expressions can be used as a statement"); + rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name); } - - public void Error_InvalidExpressionStatement () + + public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name) { - Error_InvalidExpressionStatement (loc); + rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null", + name, TypeManager.CSharpName (type)); } - protected void Error_CannotAssign (string to, string roContext) + public static void Error_InvalidExpressionStatement (Report Report, Location loc) { - Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", - to, roContext); + Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " + + "expressions can be used as a statement"); + } + + public void Error_InvalidExpressionStatement (BlockContext ec) + { + Error_InvalidExpressionStatement (ec.Report, loc); } - public static void Error_VoidInvalidInTheContext (Location loc) + public static void Error_VoidInvalidInTheContext (Location loc, Report Report) { Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); } - public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) + public virtual void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) { Error_ValueCannotBeConvertedCore (ec, loc, target, expl); } - protected void Error_ValueCannotBeConvertedCore (EmitContext ec, Location loc, Type target, bool expl) + protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl) { // The error was already reported as CS1660 if (type == InternalType.AnonymousMethod) return; +/* if (TypeManager.IsGenericParameter (Type) && TypeManager.IsGenericParameter (target) && type.Name == target.Name) { -#if GMCS_SOURCE string sig1 = type.DeclaringMethod == null ? TypeManager.CSharpName (type.DeclaringType) : TypeManager.CSharpSignature (type.DeclaringMethod); string sig2 = target.DeclaringMethod == null ? TypeManager.CSharpName (target.DeclaringType) : TypeManager.CSharpSignature (target.DeclaringMethod); - Report.ExtraInformation (loc, + ec.Report.ExtraInformation (loc, String.Format ( "The generic parameter `{0}' of `{1}' cannot be converted to the generic parameter `{0}' of `{2}' (in the previous ", Type.Name, sig1, sig2)); -#endif - } else if (Type.FullName == target.FullName){ - Report.ExtraInformation (loc, + } else if (Type.MetaInfo.FullName == target.MetaInfo.FullName) { + ec.Report.ExtraInformation (loc, String.Format ( "The type `{0}' has two conflicting definitions, one comes from `{1}' and the other from `{2}' (in the previous ", - Type.FullName, Type.Assembly.FullName, target.Assembly.FullName)); + Type.MetaInfo.FullName, Type.Assembly.FullName, target.Assembly.FullName)); } - +*/ if (expl) { - Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'", + ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'", TypeManager.CSharpName (type), TypeManager.CSharpName (target)); return; } - Report.DisableReporting (); + ec.Report.DisableReporting (); bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null; - Report.EnableReporting (); + ec.Report.EnableReporting (); if (expl_exists) { - Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " + + ec.Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. " + "An explicit conversion exists (are you missing a cast?)", TypeManager.CSharpName (Type), TypeManager.CSharpName (target)); return; } - Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", - TypeManager.CSharpName (type), - TypeManager.CSharpName (target)); + ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", + type.GetSignatureForError (), target.GetSignatureForError ()); } - public virtual void Error_VariableIsUsedBeforeItIsDeclared (string name) + public virtual void Error_VariableIsUsedBeforeItIsDeclared (Report Report, string name) { Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", name); } - protected virtual void Error_TypeDoesNotContainDefinition (Type type, string name) + public void Error_TypeArgumentsCannotBeUsed (Report report, Location loc, MemberSpec member, int arity) { - Error_TypeDoesNotContainDefinition (loc, type, name); + // Better message for possible generic expressions + if (member != null && (member.Kind & MemberKind.GenericMask) != 0) { + report.SymbolRelatedToPreviousError (member); + if (member is TypeSpec) + member = ((TypeSpec) member).GetDefinition (); + else + member = ((MethodSpec) member).GetGenericMethodDefinition (); + + string name = member.Kind == MemberKind.Method ? "method" : "type"; + if (member.IsGeneric) { + report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)", + name, member.GetSignatureForError (), member.Arity.ToString ()); + } else { + report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments", + name, member.GetSignatureForError ()); + } + } else { + report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments", + ExprClassName, GetSignatureForError ()); + } } - public static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name) + protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) { - Report.SymbolRelatedToPreviousError (type); - Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'", - TypeManager.CSharpName (type), name); + Error_TypeDoesNotContainDefinition (ec, loc, type, name); } - protected static void Error_ValueAssignment (Location loc) + public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name) { - Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer"); + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'", + TypeManager.CSharpName (type), name); } - ResolveFlags ExprClassToResolveFlags + protected static void Error_ValueAssignment (ResolveContext ec, Location loc) { + ec.Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer"); + } + + public ResolveFlags ExprClassToResolveFlags { get { switch (eclass) { case ExprClass.Type: @@ -478,76 +453,43 @@ namespace Mono.CSharp { /// Currently Resolve wraps DoResolve to perform sanity /// checking and assertion checking on what we expect from Resolve. /// - public Expression Resolve (EmitContext ec, ResolveFlags flags) + public Expression Resolve (ResolveContext ec, ResolveFlags flags) { - if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) - return ResolveAsTypeStep (ec, false); - - bool do_flow_analysis = ec.DoFlowAnalysis; - bool omit_struct_analysis = ec.OmitStructFlowAnalysis; - if ((flags & ResolveFlags.DisableFlowAnalysis) != 0) - do_flow_analysis = false; - if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0) - omit_struct_analysis = true; + if (eclass != ExprClass.Unresolved) + return this; + Expression e; - using (ec.WithFlowAnalysis (do_flow_analysis, omit_struct_analysis)) { - if (this is SimpleName) { - bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate; - e = ((SimpleName) this).DoResolve (ec, intermediate); - } else { - e = DoResolve (ec); + try { + e = DoResolve (ec); + + if (e == null) + return null; + + if ((flags & e.ExprClassToResolveFlags) == 0) { + e.Error_UnexpectedKind (ec, flags, loc); + return null; } - } - if (e == null) - return null; + if (e.type == null) + throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ()); - if ((flags & e.ExprClassToResolveFlags) == 0) { - e.Error_UnexpectedKind (flags, loc); - return null; - } + return e; + } catch (Exception ex) { + if (loc.IsNull || Report.DebugFlags > 0 || ex is CompletionResult) + throw; - if (e.type == null && !(e is Namespace)) { - throw new Exception ( - "Expression " + e.GetType () + - " did not set its type after Resolve\n" + - "called from: " + this.GetType ()); + ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message); + return EmptyExpression.Null; } - - return e; } /// /// Resolves an expression and performs semantic analysis on it. /// - public Expression Resolve (EmitContext ec) - { - Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); - - if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) { - ((MethodGroupExpr) e).ReportUsageError (); - return null; - } - return e; - } - - public Constant ResolveAsConstant (EmitContext ec, MemberCore mc) + public Expression Resolve (ResolveContext rc) { - Expression e = Resolve (ec); - if (e == null) - return null; - - Constant c = e as Constant; - if (c != null) - return c; - - if (type != null && TypeManager.IsReferenceType (type)) - Const.Error_ConstantCanBeInitializedWithNullOnly (type, loc, mc.GetSignatureForError ()); - else - Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ()); - - return null; + return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); } /// @@ -558,10 +500,10 @@ namespace Mono.CSharp { /// Currently ResolveLValue wraps DoResolveLValue to perform sanity /// checking and assertion checking on what we expect from Resolve /// - public Expression ResolveLValue (EmitContext ec, Expression right_side) + public Expression ResolveLValue (ResolveContext ec, Expression right_side) { - int errors = Report.Errors; - bool out_access = right_side == EmptyExpression.OutAccess; + int errors = ec.Report.Errors; + bool out_access = right_side == EmptyExpression.OutAccess.Instance; Expression e = DoResolveLValue (ec, right_side); @@ -575,16 +517,16 @@ namespace Mono.CSharp { } if (e == null) { - if (errors == Report.Errors) { + if (errors == ec.Report.Errors) { if (out_access) - Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); + ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); else - Error_ValueAssignment (loc); + Error_ValueAssignment (ec, loc); } return null; } - if (e.eclass == ExprClass.Invalid) + if (e.eclass == ExprClass.Unresolved) throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); if ((e.type == null) && !(e is GenericTypeExpr)) @@ -593,6 +535,11 @@ namespace Mono.CSharp { return e; } + public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + Attribute.Error_AttributeArgumentNotValid (rc, loc); + } + /// /// Emits the code for the expression /// @@ -603,6 +550,7 @@ namespace Mono.CSharp { /// public abstract void Emit (EmitContext ec); + // Emit code to branch to @target if this expression is equivalent to @on_true. // The default implementation is to emit the value, and then emit a brtrue or brfalse. // Subclasses can provide more efficient implementations, but those MUST be equivalent, @@ -610,7 +558,7 @@ namespace Mono.CSharp { public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true) { Emit (ec); - ec.ig.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); + ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); } // Emit this expression for its side effects, not for its value. @@ -619,7 +567,7 @@ namespace Mono.CSharp { public virtual void EmitSideEffect (EmitContext ec) { Emit (ec); - ec.ig.Emit (OpCodes.Pop); + ec.Emit (OpCodes.Pop); } /// @@ -629,35 +577,28 @@ namespace Mono.CSharp { protected Expression () { - eclass = ExprClass.Invalid; - type = null; } /// /// Returns a fully formed expression after a MemberLookup /// /// - public static Expression ExprClassFromMemberInfo (Type container_type, MemberInfo mi, Location loc) - { - if (mi is EventInfo) - return new EventExpr ((EventInfo) mi, loc); - else if (mi is FieldInfo) { - FieldInfo fi = (FieldInfo) mi; - if (fi.IsLiteral || (fi.IsInitOnly && fi.FieldType == TypeManager.decimal_type)) - return new ConstantExpr (fi, loc); - return new FieldExpr (fi, loc); - } else if (mi is PropertyInfo) - return new PropertyExpr (container_type, (PropertyInfo) mi, loc); - else if (mi is Type) { - return new TypeExpression ((System.Type) mi, loc); - } + public static Expression ExprClassFromMemberInfo (TypeSpec container_type, MemberSpec spec, Location loc) + { + if (spec is EventSpec) + return new EventExpr ((EventSpec) spec, loc); + if (spec is ConstSpec) + return new ConstantExpr ((ConstSpec) spec, loc); + if (spec is FieldSpec) + return new FieldExpr ((FieldSpec) spec, loc); + if (spec is PropertySpec) + return new PropertyExpr ((PropertySpec) spec, loc); + if (spec is TypeSpec) + return new TypeExpression (((TypeSpec) spec), loc); return null; } - // TODO: [Obsolete ("Can be removed")] - protected static ArrayList almost_matched_members = new ArrayList (4); - // // FIXME: Probably implement a cache for (t,name,current_access_set)? // @@ -686,135 +627,64 @@ namespace Mono.CSharp { // FIXME: Potential optimization, have a static ArrayList // - public static Expression MemberLookup (Type container_type, Type queried_type, string name, - MemberTypes mt, BindingFlags bf, Location loc) + public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type, string name, int arity, + MemberKind mt, BindingRestriction bf, Location loc) { - return MemberLookup (container_type, null, queried_type, name, mt, bf, loc); + return MemberLookup (ctx, container_type, null, queried_type, name, arity, mt, bf, loc); } // // Lookup type `queried_type' for code in class `container_type' with a qualifier of // `qualifier_type' or null to lookup members in the current class. // - - public static Expression MemberLookup (Type container_type, - Type qualifier_type, Type queried_type, - string name, MemberTypes mt, - BindingFlags bf, Location loc) + public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, + TypeSpec qualifier_type, TypeSpec queried_type, + string name, int arity, MemberKind mt, + BindingRestriction binding, Location loc) { - almost_matched_members.Clear (); - - MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type, - queried_type, mt, bf, name, almost_matched_members); - + var mi = TypeManager.MemberLookup (container_type, qualifier_type, + queried_type, mt, binding, name, arity, null); if (mi == null) return null; - if (mi.Length > 1) { - bool is_interface = qualifier_type != null && qualifier_type.IsInterface; - ArrayList methods = new ArrayList (2); - ArrayList non_methods = null; - - foreach (MemberInfo m in mi) { - if (m is MethodBase) { - methods.Add (m); - continue; - } - - if (non_methods == null) - non_methods = new ArrayList (2); - - bool is_candidate = true; - for (int i = 0; i < non_methods.Count; ++i) { - MemberInfo n_m = (MemberInfo) non_methods [i]; - if (n_m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (m.DeclaringType, n_m.DeclaringType)) { - non_methods.Remove (n_m); - --i; - } else if (m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (n_m.DeclaringType, m.DeclaringType)) { - is_candidate = false; - break; - } - } - - if (is_candidate) { - non_methods.Add (m); - } - } - - if (methods.Count == 0 && non_methods != null && non_methods.Count > 1) { - Report.SymbolRelatedToPreviousError ((MemberInfo)non_methods [1]); - Report.SymbolRelatedToPreviousError ((MemberInfo)non_methods [0]); - Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", - TypeManager.GetFullNameSignature ((MemberInfo)non_methods [1]), - TypeManager.GetFullNameSignature ((MemberInfo)non_methods [0])); - return null; + var first = mi [0]; + if (mi.Count > 1) { + foreach (var mc in mi) { + if (mc is MethodSpec) + return new MethodGroupExpr (mi, queried_type, loc); } - if (methods.Count == 0) - return ExprClassFromMemberInfo (container_type, (MemberInfo)non_methods [0], loc); - - if (non_methods != null && non_methods.Count > 0) { - MethodBase method = (MethodBase) methods [0]; - MemberInfo non_method = (MemberInfo) non_methods [0]; - if (method.DeclaringType == non_method.DeclaringType) { - // Cannot happen with C# code, but is valid in IL - Report.SymbolRelatedToPreviousError (method); - Report.SymbolRelatedToPreviousError (non_method); - Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", - TypeManager.GetFullNameSignature (non_method), - TypeManager.CSharpSignature (method)); - return null; - } - - if (is_interface) { - Report.SymbolRelatedToPreviousError (method); - Report.SymbolRelatedToPreviousError (non_method); - Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'", - TypeManager.CSharpSignature (method), TypeManager.GetFullNameSignature (non_method)); - } - } - - return new MethodGroupExpr (methods, queried_type, loc); + ctx.Report.SymbolRelatedToPreviousError (mi [1]); + ctx.Report.SymbolRelatedToPreviousError (first); + ctx.Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", + first.GetSignatureForError (), mi [1].GetSignatureForError ()); } - if (mi [0] is MethodBase) + if (first is MethodSpec) return new MethodGroupExpr (mi, queried_type, loc); - return ExprClassFromMemberInfo (container_type, mi [0], loc); + return ExprClassFromMemberInfo (container_type, first, loc); } - public const MemberTypes AllMemberTypes = - MemberTypes.Constructor | - MemberTypes.Event | - MemberTypes.Field | - MemberTypes.Method | - MemberTypes.NestedType | - MemberTypes.Property; - - public const BindingFlags AllBindingFlags = - BindingFlags.Public | - BindingFlags.Static | - BindingFlags.Instance; - - public static Expression MemberLookup (Type container_type, Type queried_type, - string name, Location loc) + public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type, + string name, int arity, BindingRestriction binding, Location loc) { - return MemberLookup (container_type, null, queried_type, name, - AllMemberTypes, AllBindingFlags, loc); + return MemberLookup (ctx, container_type, null, queried_type, name, arity, + MemberKind.All, binding | BindingRestriction.AccessibleOnly, loc); } - public static Expression MemberLookup (Type container_type, Type qualifier_type, - Type queried_type, string name, Location loc) + public static Expression MemberLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec qualifier_type, + TypeSpec queried_type, string name, int arity, BindingRestriction binding, Location loc) { - return MemberLookup (container_type, qualifier_type, queried_type, - name, AllMemberTypes, AllBindingFlags, loc); + return MemberLookup (ctx, container_type, qualifier_type, queried_type, + name, arity, MemberKind.All, binding | BindingRestriction.AccessibleOnly, loc); } - public static MethodGroupExpr MethodLookup (Type container_type, Type queried_type, - string name, Location loc) + public static MethodGroupExpr MethodLookup (CompilerContext ctx, TypeSpec container_type, TypeSpec queried_type, + MemberKind kind, string name, int arity, Location loc) { - return (MethodGroupExpr)MemberLookup (container_type, null, queried_type, name, - MemberTypes.Method, AllBindingFlags, loc); + return (MethodGroupExpr)MemberLookup (ctx, container_type, null, queried_type, name, arity, + kind, BindingRestriction.AccessibleOnly, loc); } /// @@ -823,57 +693,58 @@ namespace Mono.CSharp { /// look for private members and display a useful debugging message if we /// find it. /// - protected Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, - Type queried_type, string name, - MemberTypes mt, BindingFlags bf, + protected Expression MemberLookupFinal (ResolveContext ec, TypeSpec qualifier_type, + TypeSpec queried_type, string name, int arity, + MemberKind mt, BindingRestriction bf, Location loc) { Expression e; - int errors = Report.Errors; - e = MemberLookup (ec.CurrentType, qualifier_type, queried_type, name, mt, bf, loc); + int errors = ec.Report.Errors; + e = MemberLookup (ec.Compiler, ec.CurrentType, qualifier_type, queried_type, name, arity, mt, bf, loc); - if (e != null || errors != Report.Errors) + if (e != null || errors != ec.Report.Errors) return e; // No errors were reported by MemberLookup, but there was an error. - return Error_MemberLookupFailed (ec.CurrentType, qualifier_type, queried_type, - name, null, mt, bf); + return Error_MemberLookupFailed (ec, ec.CurrentType, qualifier_type, queried_type, + name, arity, null, mt, bf); } - protected virtual Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type, - Type queried_type, string name, string class_name, - MemberTypes mt, BindingFlags bf) + protected virtual Expression Error_MemberLookupFailed (ResolveContext ec, TypeSpec container_type, TypeSpec qualifier_type, + TypeSpec queried_type, string name, int arity, string class_name, + MemberKind mt, BindingRestriction bf) { - MemberInfo[] lookup = null; + IList lookup = null; if (queried_type == null) { class_name = "global::"; } else { + BindingRestriction restriction = bf & BindingRestriction.DeclaredOnly; + lookup = TypeManager.MemberLookup (queried_type, null, queried_type, - mt, (bf & ~BindingFlags.Public) | BindingFlags.NonPublic, - name, null); + mt, restriction, name, arity, null); if (lookup != null) { - Expression e = Error_MemberLookupFailed (queried_type, lookup); + Expression e = Error_MemberLookupFailed (ec, queried_type, lookup); // // FIXME: This is still very wrong, it should be done inside // OverloadResolve to do correct arguments matching. // Requires MemberLookup accessiblity check removal // - if (e == null || (mt & (MemberTypes.Method | MemberTypes.Constructor)) == 0) { - MemberInfo mi = lookup[0]; - Report.SymbolRelatedToPreviousError (mi); - if (qualifier_type != null && container_type != null && qualifier_type != container_type && + if (e == null || (mt & (MemberKind.Method | MemberKind.Constructor)) == 0) { + var mi = lookup.First (); + ec.Report.SymbolRelatedToPreviousError (mi); + if ((mi.Modifiers & Modifiers.PROTECTED) != 0 && qualifier_type != null && container_type != null && qualifier_type != container_type && TypeManager.IsNestedFamilyAccessible (container_type, mi.DeclaringType)) { // Although a derived class can access protected members of // its base class it cannot do so through an instance of the // base class (CS1540). If the qualifier_type is a base of the // ec.CurrentType and the lookup succeeds with the latter one, // then we are in this situation. - Error_CannotAccessProtected (loc, mi, qualifier_type, container_type); + Error_CannotAccessProtected (ec, loc, mi, qualifier_type, container_type); } else { - ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (mi)); + ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (mi), ec.Report); } } @@ -881,64 +752,51 @@ namespace Mono.CSharp { } lookup = TypeManager.MemberLookup (queried_type, null, queried_type, - AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic, - name, null); + MemberKind.All, BindingRestriction.None, name, -System.Math.Max (1, arity), null); } if (lookup == null) { if (class_name != null) { - Report.Error (103, loc, "The name `{0}' does not exist in the current context", + ec.Report.Error (103, loc, "The name `{0}' does not exist in the current context", name); } else { - Error_TypeDoesNotContainDefinition (queried_type, name); + Error_TypeDoesNotContainDefinition (ec, queried_type, name); } return null; } - if (TypeManager.MemberLookup (queried_type, null, queried_type, - AllMemberTypes, AllBindingFlags | - BindingFlags.NonPublic, name, null) == null) { - if ((lookup.Length == 1) && (lookup [0] is Type)) { - Type t = (Type) lookup [0]; - - Report.Error (305, loc, - "Using the generic type `{0}' " + - "requires {1} type arguments", - TypeManager.CSharpName (t), - TypeManager.GetNumberOfTypeArguments (t).ToString ()); - return null; - } + var mge = Error_MemberLookupFailed (ec, queried_type, lookup); + if (arity > 0 && mge != null) { + mge.SetTypeArguments (ec, new TypeArguments (new FullNamedExpression [arity])); } - return Error_MemberLookupFailed (queried_type, lookup); + return mge; } - protected virtual Expression Error_MemberLookupFailed (Type type, MemberInfo[] members) + protected virtual MemberExpr Error_MemberLookupFailed (ResolveContext ec, TypeSpec type, IList members) { - for (int i = 0; i < members.Length; ++i) { - if (!(members [i] is MethodBase)) - return null; - } + if (members.Any ((m) => !(m is MethodSpec))) + return (MemberExpr) ExprClassFromMemberInfo (type, members.First (), loc); // By default propagate the closest candidates upwards return new MethodGroupExpr (members, type, loc, true); } - protected virtual void Error_NegativeArrayIndex (Location loc) + protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc) { throw new NotImplementedException (); } - protected void Error_PointerInsideExpressionTree () + protected void Error_PointerInsideExpressionTree (ResolveContext ec) { - Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation"); + ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation"); } /// /// Returns an expression that can be used to invoke operator true /// on the expression if it exists. /// - static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc) + protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, true, loc); } @@ -947,16 +805,16 @@ namespace Mono.CSharp { /// Returns an expression that can be used to invoke operator false /// on the expression if it exists. /// - static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc) + static public Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, false, loc); } - static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc) + static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc) { MethodGroupExpr operator_group; string mname = Operator.GetMetadataName (is_true ? Operator.OpType.True : Operator.OpType.False); - operator_group = MethodLookup (ec.CurrentType, e.Type, mname, loc) as MethodGroupExpr; + operator_group = MethodLookup (ec.Compiler, ec.CurrentType, e.Type, MemberKind.Operator, mname, 0, loc) as MethodGroupExpr; if (operator_group == null) return null; @@ -971,47 +829,12 @@ namespace Mono.CSharp { return new UserOperatorCall (operator_group, arguments, null, loc); } - /// - /// Resolves the expression `e' into a boolean expression: either through - /// an implicit conversion, or through an `operator true' invocation - /// - public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc) - { - e = e.Resolve (ec); - if (e == null) - return null; - - if (e.Type == TypeManager.bool_type) - return e; - - if (TypeManager.IsDynamicType (e.Type)) { - Arguments args = new Arguments (1); - args.Add (new Argument (e)); - return new DynamicUnaryConversion ("IsTrue", args, loc); - } - - Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null); - - if (converted != null) - return converted; - - // - // If no implicit conversion to bool exists, try using `operator true' - // - converted = Expression.GetOperatorTrue (ec, e, loc); - if (converted == null){ - e.Error_ValueCannotBeConverted (ec, loc, TypeManager.bool_type, false); - return null; - } - return converted; - } - public virtual string ExprClassName { get { switch (eclass){ - case ExprClass.Invalid: - return "Invalid"; + case ExprClass.Unresolved: + return "Unresolved"; case ExprClass.Value: return "value"; case ExprClass.Variable: @@ -1040,12 +863,12 @@ namespace Mono.CSharp { /// /// Reports that we were expecting `expr' to be of class `expected' /// - public void Error_UnexpectedKind (MemberCore mc, string expected, Location loc) + public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, Location loc) { - Error_UnexpectedKind (mc, expected, ExprClassName, loc); + Error_UnexpectedKind (r, mc, expected, ExprClassName, loc); } - public void Error_UnexpectedKind (MemberCore mc, string expected, string was, Location loc) + public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, string was, Location loc) { string name; if (mc != null) @@ -1053,11 +876,11 @@ namespace Mono.CSharp { else name = GetSignatureForError (); - Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", + r.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", name, was, expected); } - public void Error_UnexpectedKind (ResolveFlags flags, Location loc) + public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc) { string [] valid = new string [4]; int count = 0; @@ -1086,94 +909,26 @@ namespace Mono.CSharp { sb.Append (valid [count - 1]); } - Report.Error (119, loc, + ec.Report.Error (119, loc, "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ()); } - public static void UnsafeError (Location loc) + public static void UnsafeError (ResolveContext ec, Location loc) { - Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context"); + UnsafeError (ec.Report, loc); } - // - // Load the object from the pointer. - // - public static void LoadFromPtr (ILGenerator ig, Type t) - { - if (t == TypeManager.int32_type) - ig.Emit (OpCodes.Ldind_I4); - else if (t == TypeManager.uint32_type) - ig.Emit (OpCodes.Ldind_U4); - else if (t == TypeManager.short_type) - ig.Emit (OpCodes.Ldind_I2); - else if (t == TypeManager.ushort_type) - ig.Emit (OpCodes.Ldind_U2); - else if (t == TypeManager.char_type) - ig.Emit (OpCodes.Ldind_U2); - else if (t == TypeManager.byte_type) - ig.Emit (OpCodes.Ldind_U1); - else if (t == TypeManager.sbyte_type) - ig.Emit (OpCodes.Ldind_I1); - else if (t == TypeManager.uint64_type) - ig.Emit (OpCodes.Ldind_I8); - else if (t == TypeManager.int64_type) - ig.Emit (OpCodes.Ldind_I8); - else if (t == TypeManager.float_type) - ig.Emit (OpCodes.Ldind_R4); - else if (t == TypeManager.double_type) - ig.Emit (OpCodes.Ldind_R8); - else if (t == TypeManager.bool_type) - ig.Emit (OpCodes.Ldind_I1); - else if (t == TypeManager.intptr_type) - ig.Emit (OpCodes.Ldind_I); - else if (TypeManager.IsEnumType (t)) { - if (t == TypeManager.enum_type) - ig.Emit (OpCodes.Ldind_Ref); - else - LoadFromPtr (ig, TypeManager.GetEnumUnderlyingType (t)); - } else if (TypeManager.IsStruct (t) || TypeManager.IsGenericParameter (t)) - ig.Emit (OpCodes.Ldobj, t); - else if (t.IsPointer) - ig.Emit (OpCodes.Ldind_I); - else - ig.Emit (OpCodes.Ldind_Ref); + public static void UnsafeError (Report Report, Location loc) + { + Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context"); } - // - // The stack contains the pointer and the value of type `type' - // - public static void StoreFromPtr (ILGenerator ig, Type type) - { - if (TypeManager.IsEnumType (type)) - type = TypeManager.GetEnumUnderlyingType (type); - if (type == TypeManager.int32_type || type == TypeManager.uint32_type) - ig.Emit (OpCodes.Stind_I4); - else if (type == TypeManager.int64_type || type == TypeManager.uint64_type) - ig.Emit (OpCodes.Stind_I8); - else if (type == TypeManager.char_type || type == TypeManager.short_type || - type == TypeManager.ushort_type) - ig.Emit (OpCodes.Stind_I2); - else if (type == TypeManager.float_type) - ig.Emit (OpCodes.Stind_R4); - else if (type == TypeManager.double_type) - ig.Emit (OpCodes.Stind_R8); - else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type || - type == TypeManager.bool_type) - ig.Emit (OpCodes.Stind_I1); - else if (type == TypeManager.intptr_type) - ig.Emit (OpCodes.Stind_I); - else if (TypeManager.IsStruct (type) || TypeManager.IsGenericParameter (type)) - ig.Emit (OpCodes.Stobj, type); - else - ig.Emit (OpCodes.Stind_Ref); - } - + // // Returns the size of type `t' if known, otherwise, 0 // - public static int GetTypeSize (Type t) + public static int GetTypeSize (TypeSpec t) { - t = TypeManager.TypeToCoreType (t); if (t == TypeManager.int32_type || t == TypeManager.uint32_type || t == TypeManager.float_type) @@ -1196,43 +951,37 @@ namespace Mono.CSharp { return 0; } - protected void Error_CannotCallAbstractBase (string name) + protected void Error_CannotCallAbstractBase (ResolveContext ec, string name) { - Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name); + ec.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name); } - protected void Error_CannotModifyIntermediateExpressionValue (EmitContext ec) + protected void Error_CannotModifyIntermediateExpressionValue (ResolveContext ec) { - Report.SymbolRelatedToPreviousError (type); + ec.Report.SymbolRelatedToPreviousError (type); if (ec.CurrentInitializerVariable != null) { - Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer", + ec.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer", TypeManager.CSharpName (type), GetSignatureForError ()); } else { - Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable", + ec.Report.Error (1612, loc, "Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable", GetSignatureForError ()); } } - public void Error_ExpressionCannotBeGeneric (Location loc) - { - Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments", - ExprClassName, GetSignatureForError ()); - } - // // Converts `source' to an int, uint, long or ulong. // - protected Expression ConvertExpressionToArrayIndex (EmitContext ec, Expression source) + protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source) { - if (TypeManager.IsDynamicType (source.type)) { + if (source.type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (source)); - return new DynamicConversion (TypeManager.int32_type, false, args, loc).Resolve (ec); + return new DynamicConversion (TypeManager.int32_type, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec); } Expression converted; - using (ec.Set (EmitContext.Options.CheckedScope)) { + using (ec.Set (ResolveContext.Options.CheckedScope)) { converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc); @@ -1251,12 +1000,12 @@ namespace Mono.CSharp { // Only positive constants are allowed at compile time // Constant c = converted as Constant; - if (c != null) { - if (c.IsNegative) { - Error_NegativeArrayIndex (source.loc); - } - return c; - } + if (c != null && c.IsNegative) + Error_NegativeArrayIndex (ec, source.loc); + + // No conversion needed to array index + if (converted.Type == TypeManager.int32_type) + return converted; return new ArrayIndexCast (converted).Resolve (ec); } @@ -1297,28 +1046,28 @@ namespace Mono.CSharp { // // Implementation of expression to expression tree conversion // - public abstract Expression CreateExpressionTree (EmitContext ec); + public abstract Expression CreateExpressionTree (ResolveContext ec); - protected Expression CreateExpressionFactoryCall (string name, Arguments args) + protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args) { - return CreateExpressionFactoryCall (name, null, args, loc); + return CreateExpressionFactoryCall (ec, name, null, args, loc); } - protected Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, Arguments args) + protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args) { - return CreateExpressionFactoryCall (name, typeArguments, args, loc); + return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc); } - public static Expression CreateExpressionFactoryCall (string name, TypeArguments typeArguments, Arguments args, Location loc) + public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc) { - return new Invocation (new MemberAccess (CreateExpressionTypeExpression (loc), name, typeArguments, loc), args); + return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args); } - protected static TypeExpr CreateExpressionTypeExpression (Location loc) + protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc) { TypeExpr texpr = TypeManager.expression_type_expr; if (texpr == null) { - Type t = TypeManager.CoreLookupType ("System.Linq.Expressions", "Expression", Kind.Class, true); + TypeSpec t = TypeManager.CoreLookupType (ec.Compiler, "System.Linq.Expressions", "Expression", MemberKind.Class, true); if (t == null) return null; @@ -1328,9 +1077,14 @@ namespace Mono.CSharp { return texpr; } - public virtual void MutateHoistedGenericType (AnonymousMethodStorey storey) + // + // Implemented by all expressions which support conversion from + // compiler expression to invokable runtime expression. Used by + // dynamic C# binder. + // + public virtual SLE.Expression MakeExpression (BuilderContext ctx) { - // TODO: It should probably be type = storey.MutateType (type); + throw new NotImplementedException ("MakeExpression for " + GetType ()); } } @@ -1343,7 +1097,7 @@ namespace Mono.CSharp { /// public abstract class ExpressionStatement : Expression { - public virtual ExpressionStatement ResolveStatement (EmitContext ec) + public ExpressionStatement ResolveStatement (BlockContext ec) { Expression e = Resolve (ec); if (e == null) @@ -1351,7 +1105,7 @@ namespace Mono.CSharp { ExpressionStatement es = e as ExpressionStatement; if (es == null) - Error_InvalidExpressionStatement (); + Error_InvalidExpressionStatement (ec); return es; } @@ -1386,7 +1140,7 @@ namespace Mono.CSharp { { protected readonly Expression child; - protected TypeCast (Expression child, Type return_type) + protected TypeCast (Expression child, TypeSpec return_type) { eclass = child.eclass; loc = child.Location; @@ -1394,19 +1148,25 @@ namespace Mono.CSharp { this.child = child; } - public override Expression CreateExpressionTree (EmitContext ec) + public Expression Child { + get { + return child; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); args.Add (new Argument (child.CreateExpressionTree (ec))); args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); if (type.IsPointer || child.Type.IsPointer) - Error_PointerInsideExpressionTree (); + Error_PointerInsideExpressionTree (ec); - return CreateExpressionFactoryCall (ec.HasSet (EmitContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args); + return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { // This should never be invoked, we are born in fully // initialized state. @@ -1419,15 +1179,11 @@ namespace Mono.CSharp { child.Emit (ec); } - public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value) - { - return child.GetAttributableValue (ec, value_type, out value); - } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override SLE.Expression MakeExpression (BuilderContext ctx) { - type = storey.MutateType (type); - child.MutateHoistedGenericType (storey); + return ctx.HasSet (BuilderContext.Options.CheckedScope) ? + SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) : + SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ()); } protected override void CloneTo (CloneContext clonectx, Expression t) @@ -1441,12 +1197,12 @@ namespace Mono.CSharp { } public class EmptyCast : TypeCast { - EmptyCast (Expression child, Type target_type) + EmptyCast (Expression child, TypeSpec target_type) : base (child, target_type) { } - public static Expression Create (Expression child, Type type) + public static Expression Create (Expression child, TypeSpec type) { Constant c = child as Constant; if (c != null) @@ -1474,14 +1230,14 @@ namespace Mono.CSharp { // Used for predefined class library user casts (no obsolete check, etc.) // public class OperatorCast : TypeCast { - MethodInfo conversion_operator; + MethodSpec conversion_operator; - public OperatorCast (Expression child, Type target_type) + public OperatorCast (Expression child, TypeSpec target_type) : this (child, target_type, false) { } - public OperatorCast (Expression child, Type target_type, bool find_explicit) + public OperatorCast (Expression child, TypeSpec target_type, bool find_explicit) : base (child, target_type) { conversion_operator = GetConversionOperator (find_explicit); @@ -1491,24 +1247,23 @@ namespace Mono.CSharp { // Returns the implicit operator that converts from // 'child.Type' to our target type (type) - MethodInfo GetConversionOperator (bool find_explicit) + MethodSpec GetConversionOperator (bool find_explicit) { string operator_name = find_explicit ? "op_Explicit" : "op_Implicit"; - MemberInfo [] mi; - - mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberTypes.Method, - BindingFlags.Static | BindingFlags.Public, operator_name, null); + // Operators are always public + var mi = TypeManager.MemberLookup (child.Type, child.Type, child.Type, MemberKind.Operator, + BindingRestriction.None, operator_name, 0, null); if (mi == null){ - mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method, - BindingFlags.Static | BindingFlags.Public, operator_name, null); + mi = TypeManager.MemberLookup (type, type, type, MemberKind.Operator, + BindingRestriction.None, operator_name, 0, null); } - foreach (MethodInfo oper in mi) { - AParametersCollection pd = TypeManager.GetParameterData (oper); + foreach (MethodSpec oper in mi) { + AParametersCollection pd = oper.Parameters; - if (pd.Types [0] == child.Type && TypeManager.TypeToCoreType (oper.ReturnType) == type) + if (pd.Types [0] == child.Type && oper.ReturnType == type) return oper; } @@ -1518,7 +1273,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { child.Emit (ec); - ec.ig.Emit (OpCodes.Call, conversion_operator); + ec.Emit (OpCodes.Call, conversion_operator); } } @@ -1542,14 +1297,13 @@ namespace Mono.CSharp { /// public class CastFromDecimal : TypeCast { - static IDictionary operators; + static Dictionary operators; - public CastFromDecimal (Expression child, Type return_type) + public CastFromDecimal (Expression child, TypeSpec return_type) : base (child, return_type) { if (child.Type != TypeManager.decimal_type) - throw new InternalErrorException ( - "The expected type is Decimal, instead it is " + child.Type.FullName); + throw new ArgumentException ("Expected decimal child " + child.Type.GetSignatureForError ()); } // Returns the explicit operator that converts from an @@ -1557,27 +1311,31 @@ namespace Mono.CSharp { public Expression Resolve () { if (operators == null) { - MemberInfo[] all_oper = TypeManager.MemberLookup (TypeManager.decimal_type, - TypeManager.decimal_type, TypeManager.decimal_type, MemberTypes.Method, - BindingFlags.Static | BindingFlags.Public, "op_Explicit", null); + var all_oper = TypeManager.MemberLookup (TypeManager.decimal_type, + TypeManager.decimal_type, TypeManager.decimal_type, MemberKind.Operator, + BindingRestriction.None, "op_Explicit", 0, null); - operators = new System.Collections.Specialized.HybridDictionary (); - foreach (MethodInfo oper in all_oper) { - AParametersCollection pd = TypeManager.GetParameterData (oper); + operators = new Dictionary (); + foreach (MethodSpec oper in all_oper) { + AParametersCollection pd = oper.Parameters; if (pd.Types [0] == TypeManager.decimal_type) - operators.Add (TypeManager.TypeToCoreType (oper.ReturnType), oper); + operators.Add (oper.ReturnType, oper); } } - return operators.Contains (type) ? this : null; + return operators.ContainsKey (type) ? this : null; } public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; child.Emit (ec); - ig.Emit (OpCodes.Call, (MethodInfo)operators [type]); + ec.Emit (OpCodes.Call, operators [type]); + } + + public static void Reset () + { + operators = null; } } @@ -1589,13 +1347,16 @@ namespace Mono.CSharp { // public class EmptyConstantCast : Constant { - public readonly Constant child; + public Constant child; - public EmptyConstantCast(Constant child, Type type) + public EmptyConstantCast (Constant child, TypeSpec type) : base (child.Location) { - eclass = child.eclass; + if (child == null) + throw new ArgumentNullException ("child"); + this.child = child; + this.eclass = child.eclass; this.type = type; } @@ -1609,27 +1370,25 @@ namespace Mono.CSharp { return child.GetValue (); } - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { + if (child.Type == target_type) + return child; + // FIXME: check that 'type' can be converted to 'target_type' first return child.ConvertExplicitly (in_checked_context, target_type); } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = Arguments.CreateForExpressionTree (ec, null, child.CreateExpressionTree (ec), new TypeOf (new TypeExpression (type, loc), loc)); if (type.IsPointer) - Error_PointerInsideExpressionTree (); - - return CreateExpressionFactoryCall ("Convert", args); - } + Error_PointerInsideExpressionTree (ec); - public override Constant Increment () - { - return child.Increment (); + return CreateExpressionFactoryCall (ec, "Convert", args); } public override bool IsDefaultValue { @@ -1643,10 +1402,19 @@ namespace Mono.CSharp { public override bool IsNull { get { return child.IsNull; } } + + public override bool IsOneInteger { + get { return child.IsOneInteger; } + } public override bool IsZeroInteger { get { return child.IsZeroInteger; } } + + protected override Expression DoResolve (ResolveContext rc) + { + return this; + } public override void Emit (EmitContext ec) { @@ -1657,11 +1425,9 @@ namespace Mono.CSharp { { child.EmitBranchable (ec, label, on_true); -#if GMCS_SOURCE // Only to make verifier happy if (TypeManager.IsGenericParameter (type) && child.IsNull) - ec.ig.Emit (OpCodes.Unbox_Any, type); -#endif + ec.Emit (OpCodes.Unbox_Any, type); } public override void EmitSideEffect (EmitContext ec) @@ -1669,40 +1435,38 @@ namespace Mono.CSharp { child.EmitSideEffect (ec); } - public override Constant ConvertImplicitly (Type target_type) + public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec target_type) { // FIXME: Do we need to check user conversions? if (!Convert.ImplicitStandardConversionExists (this, target_type)) return null; - return child.ConvertImplicitly (target_type); - } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - child.MutateHoistedGenericType (storey); + return child.ConvertImplicitly (rc, target_type); } } - /// /// This class is used to wrap literals which belong inside Enums /// - public class EnumConstant : Constant { + public class EnumConstant : Constant + { public Constant Child; - public EnumConstant (Constant child, Type enum_type): - base (child.Location) + public EnumConstant (Constant child, TypeSpec enum_type) + : base (child.Location) { - eclass = child.eclass; this.Child = child; - type = enum_type; + this.type = enum_type; } - - public override Expression DoResolve (EmitContext ec) + + protected EnumConstant (Location loc) + : base (loc) { - // This should never be invoked, we are born in fully - // initialized state. + } + protected override Expression DoResolve (ResolveContext rc) + { + Child = Child.Resolve (rc); + this.eclass = ExprClass.Value; return this; } @@ -1711,6 +1475,11 @@ namespace Mono.CSharp { Child.Emit (ec); } + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + Child.EncodeAttributeValue (rc, enc, Child.Type); + } + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) { Child.EmitBranchable (ec, label, on_true); @@ -1721,12 +1490,6 @@ namespace Mono.CSharp { Child.EmitSideEffect (ec); } - public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value) - { - value = GetTypedValue (); - return true; - } - public override string GetSignatureForError() { return TypeManager.CSharpName (Type); @@ -1752,11 +1515,11 @@ namespace Mono.CSharp { // // This works only sometimes // - if (type.Module == RootContext.ToplevelTypes.Builder) + if (type.MemberDefinition is TypeContainer) return Child.GetValue (); #endif - return System.Enum.ToObject (type, Child.GetValue ()); + return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ()); } public override string AsString () @@ -1764,9 +1527,9 @@ namespace Mono.CSharp { return Child.AsString (); } - public override Constant Increment() + public EnumConstant Increment() { - return new EnumConstant (Child.Increment (), type); + return new EnumConstant (((IntegralConstant) Child).Increment (), type); } public override bool IsDefaultValue { @@ -1785,7 +1548,7 @@ namespace Mono.CSharp { } } - public override Constant ConvertExplicitly(bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly(bool in_checked_context, TypeSpec target_type) { if (Child.Type == target_type) return Child; @@ -1793,19 +1556,9 @@ namespace Mono.CSharp { return Child.ConvertExplicitly (in_checked_context, target_type); } - public override Constant ConvertImplicitly (Type type) + public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec type) { - Type this_type = TypeManager.DropGenericTypeArguments (Type); - type = TypeManager.DropGenericTypeArguments (type); - - if (this_type == type) { - // This is workaround of mono bug. It can be removed when the latest corlib spreads enough - if (TypeManager.IsEnumType (type.UnderlyingSystemType)) - return this; - - Type child_type = TypeManager.DropGenericTypeArguments (Child.Type); - if (type.UnderlyingSystemType != child_type) - Child = Child.ConvertImplicitly (type.UnderlyingSystemType); + if (this.type == type) { return this; } @@ -1813,9 +1566,8 @@ namespace Mono.CSharp { return null; } - return Child.ConvertImplicitly(type); + return Child.ConvertImplicitly (rc, type); } - } /// @@ -1826,13 +1578,13 @@ namespace Mono.CSharp { /// public class BoxedCast : TypeCast { - public BoxedCast (Expression expr, Type target_type) + public BoxedCast (Expression expr, TypeSpec target_type) : base (expr, target_type) { eclass = ExprClass.Value; } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { // This should never be invoked, we are born in fully // initialized state. @@ -1840,11 +1592,17 @@ namespace Mono.CSharp { return this; } + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (child.Type); + child.EncodeAttributeValue (rc, enc, child.Type); + } + public override void Emit (EmitContext ec) { base.Emit (ec); - ec.ig.Emit (OpCodes.Box, child.Type); + ec.Emit (OpCodes.Box, child.Type); } public override void EmitSideEffect (EmitContext ec) @@ -1860,12 +1618,12 @@ namespace Mono.CSharp { } public class UnboxCast : TypeCast { - public UnboxCast (Expression expr, Type return_type) + public UnboxCast (Expression expr, TypeSpec return_type) : base (expr, return_type) { } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { // This should never be invoked, we are born in fully // initialized state. @@ -1873,10 +1631,10 @@ namespace Mono.CSharp { return this; } - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) { if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) - Report.Error (445, loc, "Cannot modify the result of an unboxing conversion"); + ec.Report.Error (445, loc, "Cannot modify the result of an unboxing conversion"); return base.DoResolveLValue (ec, right_side); } @@ -1884,20 +1642,7 @@ namespace Mono.CSharp { { base.Emit (ec); - ILGenerator ig = ec.ig; - -#if GMCS_SOURCE - ig.Emit (OpCodes.Unbox_Any, type); -#else - ig.Emit (OpCodes.Unbox, type); - LoadFromPtr (ig, type); -#endif - } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - base.MutateHoistedGenericType (storey); + ec.Emit (OpCodes.Unbox_Any, type); } } @@ -1916,22 +1661,23 @@ namespace Mono.CSharp { U2_I1, U2_U1, U2_I2, U2_CH, I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH, U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH, - I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, - U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, + I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, I8_I, + U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I, CH_I1, CH_U1, CH_I2, R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH, - R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4 + R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4, + I_I8, } Mode mode; - public ConvCast (Expression child, Type return_type, Mode m) + public ConvCast (Expression child, TypeSpec return_type, Mode m) : base (child, return_type) { mode = m; } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { // This should never be invoked, we are born in fully // initialized state. @@ -1946,171 +1692,177 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - base.Emit (ec); - if (ec.HasSet (EmitContext.Options.CheckedScope)){ + if (ec.HasSet (EmitContext.Options.CheckedScope)) { switch (mode){ - case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break; - case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break; - case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break; - case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I1_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I1_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I1_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I1_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I1_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U1_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; case Mode.U1_CH: /* nothing */ break; - case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break; - case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break; - case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break; - case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break; - case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I2_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I2_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I2_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I2_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I2_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I2_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break; - case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break; - case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U2_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U2_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U2_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; case Mode.U2_CH: /* nothing */ break; - case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break; - case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break; - case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break; - case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break; - case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break; - case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break; - - case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break; - case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break; - case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break; - case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break; - case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break; - case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break; - - case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break; - case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break; - case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break; - case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break; - case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break; - case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break; - case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break; - - case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break; - case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break; - case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break; - case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break; - case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break; - case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break; - case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break; - case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break; - - case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break; - case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break; - case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break; - - case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break; - case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break; - case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break; - case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break; - case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break; - case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break; - case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break; - case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break; - - case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break; - case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break; - case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break; - case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break; - case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break; - case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break; - case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break; - case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break; - case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break; + case Mode.I4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.I4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U4_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U4_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U4_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U4_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U4_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break; + case Mode.U4_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + + case Mode.I8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.I8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.I8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I8_I: ec.Emit (OpCodes.Conv_Ovf_U); break; + + case Mode.U8_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U8_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U8_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U8_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U8_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break; + case Mode.U8_U4: ec.Emit (OpCodes.Conv_Ovf_U4_Un); break; + case Mode.U8_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break; + case Mode.U8_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U8_I: ec.Emit (OpCodes.Conv_Ovf_U_Un); break; + + case Mode.CH_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.CH_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.CH_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + + case Mode.R4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.R4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.R4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.R4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R4_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.R4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.R4_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break; + case Mode.R4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.R4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.R8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.R8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.R8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.R8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.R8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.R8_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break; + case Mode.R8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.R8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break; + + case Mode.I_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break; } } else { switch (mode){ - case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break; - case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break; - case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break; - case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break; - case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break; + case Mode.I1_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I1_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I1_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I1_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I1_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U1_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U1_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.I2_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I2_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I2_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I2_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I2_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I2_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U2_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U2_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U2_I2: ec.Emit (OpCodes.Conv_I2); break; case Mode.U2_CH: /* nothing */ break; - case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break; + case Mode.I4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I4_I2: ec.Emit (OpCodes.Conv_I2); break; case Mode.I4_U4: /* nothing */ break; - case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break; - case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break; - case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break; + case Mode.I4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I4_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U4_U2: ec.Emit (OpCodes.Conv_U2); break; case Mode.U4_I4: /* nothing */ break; - case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break; - case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break; - case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break; + case Mode.U4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.I8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.I8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.I8_U4: ec.Emit (OpCodes.Conv_U4); break; case Mode.I8_U8: /* nothing */ break; - case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break; - case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break; - case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break; + case Mode.I8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I8_I: ec.Emit (OpCodes.Conv_U); break; + + case Mode.U8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.U8_U4: ec.Emit (OpCodes.Conv_U4); break; case Mode.U8_I8: /* nothing */ break; - case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break; - - case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break; - case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break; - case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break; - case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break; - case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break; - case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break; - - case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break; - case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break; - case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break; - case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break; - case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break; - case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break; - case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break; - case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break; - case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break; - case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break; + case Mode.U8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U8_I: ec.Emit (OpCodes.Conv_U); break; + + case Mode.CH_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.CH_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.CH_I2: ec.Emit (OpCodes.Conv_I2); break; + + case Mode.R4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.R4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.R4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.R4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R4_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.R4_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.R4_I8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.R4_U8: ec.Emit (OpCodes.Conv_U8); break; + case Mode.R4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.R8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.R8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.R8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.R8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.R8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.R8_I8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.R8_U8: ec.Emit (OpCodes.Conv_U8); break; + case Mode.R8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break; + + case Mode.I_I8: ec.Emit (OpCodes.Conv_U8); break; } } } @@ -2119,13 +1871,13 @@ namespace Mono.CSharp { public class OpcodeCast : TypeCast { readonly OpCode op; - public OpcodeCast (Expression child, Type return_type, OpCode op) + public OpcodeCast (Expression child, TypeSpec return_type, OpCode op) : base (child, return_type) { this.op = op; } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { // This should never be invoked, we are born in fully // initialized state. @@ -2136,10 +1888,10 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { base.Emit (ec); - ec.ig.Emit (op); + ec.Emit (op); } - public Type UnderlyingType { + public TypeSpec UnderlyingType { get { return child.Type; } } } @@ -2151,12 +1903,12 @@ namespace Mono.CSharp { public sealed class ClassCast : TypeCast { readonly bool forced; - public ClassCast (Expression child, Type return_type) + public ClassCast (Expression child, TypeSpec return_type) : base (child, return_type) { } - public ClassCast (Expression child, Type return_type, bool forced) + public ClassCast (Expression child, TypeSpec return_type, bool forced) : base (child, return_type) { this.forced = forced; @@ -2166,21 +1918,19 @@ namespace Mono.CSharp { { base.Emit (ec); -#if GMCS_SOURCE bool gen = TypeManager.IsGenericParameter (child.Type); if (gen) - ec.ig.Emit (OpCodes.Box, child.Type); + ec.Emit (OpCodes.Box, child.Type); if (type.IsGenericParameter) { - ec.ig.Emit (OpCodes.Unbox_Any, type); + ec.Emit (OpCodes.Unbox_Any, type); return; } if (gen && !forced) return; -#endif - ec.ig.Emit (OpCodes.Castclass, type); + ec.Emit (OpCodes.Castclass, type); } } @@ -2200,31 +1950,21 @@ namespace Mono.CSharp { this.orig_expr = orig_expr; } - public override Constant ConvertImplicitly (Type target_type) + public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec target_type) { - Constant c = base.ConvertImplicitly (target_type); + Constant c = base.ConvertImplicitly (rc, target_type); if (c != null) c = new ReducedConstantExpression (c, orig_expr); + return c; } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { return orig_expr.CreateExpressionTree (ec); } - public override bool GetAttributableValue (EmitContext ec, Type value_type, out object value) - { - // - // Even if resolved result is a constant original expression was not - // and attribute accepts constants only - // - Attribute.Error_AttributeArgumentNotValid (orig_expr.Location); - value = null; - return false; - } - - public override Constant ConvertExplicitly (bool in_checked_context, Type target_type) + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) { Constant c = base.ConvertExplicitly (in_checked_context, target_type); if (c != null) @@ -2245,12 +1985,12 @@ namespace Mono.CSharp { this.loc = orig.Location; } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { return orig_expr.CreateExpressionTree (ec); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { eclass = stm.eclass; type = stm.Type; @@ -2266,11 +2006,6 @@ namespace Mono.CSharp { { stm.EmitStatement (ec); } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - stm.MutateHoistedGenericType (storey); - } } readonly Expression expr, orig_expr; @@ -2278,12 +2013,20 @@ namespace Mono.CSharp { private ReducedExpression (Expression expr, Expression orig_expr) { this.expr = expr; + this.eclass = expr.eclass; + this.type = expr.Type; this.orig_expr = orig_expr; this.loc = orig_expr.Location; } + // + // Creates fully resolved expression switcher + // public static Constant Create (Constant expr, Expression original_expr) { + if (expr.eclass == ExprClass.Unresolved) + throw new ArgumentException ("Unresolved expression"); + return new ReducedConstantExpression (expr, original_expr); } @@ -2292,6 +2035,10 @@ namespace Mono.CSharp { return new ReducedExpressionStatement (s, orig); } + // + // Creates unresolved reduce expression. The original expression has to be + // already resolved + // public static Expression Create (Expression expr, Expression original_expr) { Constant c = expr as Constant; @@ -2302,18 +2049,19 @@ namespace Mono.CSharp { if (s != null) return Create (s, original_expr); + if (expr.eclass == ExprClass.Unresolved) + throw new ArgumentException ("Unresolved expression"); + return new ReducedExpression (expr, original_expr); } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { return orig_expr.CreateExpressionTree (ec); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { - eclass = expr.eclass; - type = expr.Type; return this; } @@ -2327,59 +2075,129 @@ namespace Mono.CSharp { expr.EmitBranchable (ec, target, on_true); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override SLE.Expression MakeExpression (BuilderContext ctx) { - expr.MutateHoistedGenericType (storey); + return orig_expr.MakeExpression (ctx); } } // - // Unresolved type name expressions + // Standard composite pattern // - public abstract class ATypeNameExpression : FullNamedExpression + public abstract class CompositeExpression : Expression { - string name; - protected TypeArguments targs; + Expression expr; - protected ATypeNameExpression (string name, Location l) + protected CompositeExpression (Expression expr) { - this.name = name; - loc = l; + this.expr = expr; + this.loc = expr.Location; } - protected ATypeNameExpression (string name, TypeArguments targs, Location l) + public override Expression CreateExpressionTree (ResolveContext ec) { - this.name = name; - this.targs = targs; - loc = l; + return expr.CreateExpressionTree (ec); } - public bool HasTypeArguments { - get { - return targs != null; + public Expression Child { + get { return expr; } + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr != null) { + type = expr.Type; + eclass = expr.eclass; } + + return this; } - public override bool Equals (object obj) + public override void Emit (EmitContext ec) { - ATypeNameExpression atne = obj as ATypeNameExpression; - return atne != null && atne.Name == Name && - (targs == null || targs.Equals (atne.targs)); + expr.Emit (ec); } - public override int GetHashCode () + public override bool IsNull { + get { return expr.IsNull; } + } + } + + // + // Base of expressions used only to narrow resolve flow + // + public abstract class ShimExpression : Expression + { + protected Expression expr; + + protected ShimExpression (Expression expr) { - return Name.GetHashCode (); + this.expr = expr; } - public override string GetSignatureForError () + protected override void CloneTo (CloneContext clonectx, Expression t) { - if (targs != null) { - return TypeManager.RemoveGenericArity (Name) + "<" + - targs.GetSignatureForError () + ">"; + if (expr == null) + return; + + ShimExpression target = (ShimExpression) t; + target.expr = expr.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("Missing Resolve call"); + } + + public Expression Expr { + get { return expr; } + } + } + + // + // Unresolved type name expressions + // + public abstract class ATypeNameExpression : FullNamedExpression + { + string name; + protected TypeArguments targs; + + protected ATypeNameExpression (string name, Location l) + { + this.name = name; + loc = l; + } + + protected ATypeNameExpression (string name, TypeArguments targs, Location l) + { + this.name = name; + this.targs = targs; + loc = l; + } + + protected ATypeNameExpression (string name, int arity, Location l) + : this (name, new UnboundTypeArguments (arity), l) + { + } + + #region Properties + + protected int Arity { + get { + return targs == null ? 0 : targs.Count; } + } - return Name; + public bool HasTypeArguments { + get { + return targs != null && !targs.IsEmpty; + } } public string Name { @@ -2396,15 +2214,56 @@ namespace Mono.CSharp { return targs; } } + + #endregion + + public override bool Equals (object obj) + { + ATypeNameExpression atne = obj as ATypeNameExpression; + return atne != null && atne.Name == Name && + (targs == null || targs.Equals (atne.targs)); + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + // TODO: Move it to MemberCore + public static string GetMemberType (MemberCore mc) + { + if (mc is Property) + return "property"; + if (mc is Indexer) + return "indexer"; + if (mc is FieldBase) + return "field"; + if (mc is MethodCore) + return "method"; + if (mc is EnumMember) + return "enum"; + if (mc is Event) + return "event"; + + return "type"; + } + + public override string GetSignatureForError () + { + if (targs != null) { + return Name + "<" + targs.GetSignatureForError () + ">"; + } + + return Name; + } } /// /// SimpleName expressions are formed of a single word and only happen at the beginning /// of a dotted-name. /// - public class SimpleName : ATypeNameExpression { - bool in_transit; - + public class SimpleName : ATypeNameExpression + { public SimpleName (string name, Location l) : base (name, l) { @@ -2415,143 +2274,89 @@ namespace Mono.CSharp { { } - public SimpleName (string name, TypeParameter[] type_params, Location l) - : base (name, l) + public SimpleName (string name, int arity, Location l) + : base (name, arity, l) { - targs = new TypeArguments (); - foreach (TypeParameter type_param in type_params) - targs.Add (new TypeParameterExpr (type_param, l)); - } - - public static string RemoveGenericArity (string name) - { - int start = 0; - StringBuilder sb = null; - do { - int pos = name.IndexOf ('`', start); - if (pos < 0) { - if (start == 0) - return name; - - sb.Append (name.Substring (start)); - break; - } - - if (sb == null) - sb = new StringBuilder (); - sb.Append (name.Substring (start, pos-start)); - - pos++; - while ((pos < name.Length) && Char.IsNumber (name [pos])) - pos++; - - start = pos; - } while (start < name.Length); - - return sb.ToString (); } public SimpleName GetMethodGroup () { - return new SimpleName (RemoveGenericArity (Name), targs, loc); + return new SimpleName (Name, targs, loc); } - public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) + protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ec) { - if (ec.HasSet (EmitContext.Options.FieldInitializerScope)) - Report.Error (236, l, - "A field initializer cannot reference the nonstatic field, method, or property `{0}'", - name); - else - Report.Error (120, l, - "An object reference is required to access non-static member `{0}'", - name); - } + if (ec.CurrentType != null) { + if (ec.CurrentMemberDefinition != null) { + MemberCore mc = ec.CurrentMemberDefinition.Parent.GetDefinition (Name); + if (mc != null) { + Error_UnexpectedKind (ec.Compiler.Report, mc, "type", GetMemberType (mc), loc); + return; + } + } - public bool IdenticalNameAndTypeName (IResolveContext mc, Expression resolved_to, Location loc) - { - return resolved_to != null && resolved_to.Type != null && - resolved_to.Type.Name == Name && - (mc.LookupNamespaceOrType (Name, loc, /* ignore_cs0104 = */ true) != null); + /* + // TODO MemberCache: Implement + + string ns = ec.CurrentType.Namespace; + string fullname = (ns.Length > 0) ? ns + "." + Name : Name; + foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) { + var type = a.GetType (fullname); + if (type != null) { + ec.Compiler.Report.SymbolRelatedToPreviousError (type); + Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type), ec.Compiler.Report); + return; + } + } + + if (ec.CurrentTypeDefinition != null) { + TypeSpec t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name); + if (t != null) { + Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, t, loc); + return; + } + } + */ + } + + FullNamedExpression retval = ec.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), loc, true); + if (retval != null) { + Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc, retval.Type, Arity); +/* + var te = retval as TypeExpr; + if (HasTypeArguments && te != null && !te.Type.IsGeneric) + retval.Error_TypeArgumentsCannotBeUsed (ec.Compiler.Report, loc); + else + Namespace.Error_InvalidNumberOfTypeArguments (ec.Compiler.Report, retval.Type, loc); +*/ + return; + } + + NamespaceEntry.Error_NamespaceNotFound (loc, Name, ec.Compiler.Report); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { return SimpleNameResolve (ec, null, false); } - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) { return SimpleNameResolve (ec, right_side, false); } - - public Expression DoResolve (EmitContext ec, bool intermediate) + public Expression DoResolve (ResolveContext ec, bool intermediate) { return SimpleNameResolve (ec, null, intermediate); } - static bool IsNestedChild (Type t, Type parent) + public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent) { - while (parent != null) { - if (TypeManager.IsNestedChildOf (t, TypeManager.DropGenericTypeArguments (parent))) - return true; - - parent = parent.BaseType; - } - - return false; - } - - FullNamedExpression ResolveNested (IResolveContext ec, Type t) - { - if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t)) - return null; - - if (ec.CurrentType == null) - return null; - - DeclSpace ds = ec.CurrentTypeDefinition; - while (ds != null && !IsNestedChild (t, ds.TypeBuilder)) - ds = ds.Parent; - - if (ds == null) - return null; - - Type[] gen_params = TypeManager.GetTypeArguments (t); - - int arg_count = targs != null ? targs.Count : 0; - - for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) { - if (arg_count + ds.CountTypeParameters == gen_params.Length) { - TypeArguments new_args = new TypeArguments (); - foreach (TypeParameter param in ds.TypeParameters) - new_args.Add (new TypeParameterExpr (param, loc)); - - if (targs != null) - new_args.Add (targs); - - return new GenericTypeExpr (t, new_args, loc); - } - } - - return null; - } - - public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) - { - int errors = Report.Errors; - FullNamedExpression fne = ec.LookupNamespaceOrType (Name, loc, /*ignore_cs0104=*/ false); + int errors = ec.Compiler.Report.Errors; + FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, loc, /*ignore_cs0104=*/ false); if (fne != null) { - if (fne.Type == null) - return fne; - - FullNamedExpression nested = ResolveNested (ec, fne.Type); - if (nested != null) - return nested.ResolveAsTypeStep (ec, false); - - if (targs != null) { + if (HasTypeArguments && fne.Type != null && TypeManager.IsGenericType (fne.Type)) { GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); return ct.ResolveAsTypeStep (ec, false); } @@ -2559,86 +2364,29 @@ namespace Mono.CSharp { return fne; } - if (!HasTypeArguments && Name == "dynamic" && RootContext.Version > LanguageVersion.V_3) - return new DynamicTypeExpr (loc); - - if (silent || errors != Report.Errors) - return null; - - Error_TypeOrNamespaceNotFound (ec); - return null; - } + if (!HasTypeArguments && Name == "dynamic" && + RootContext.Version > LanguageVersion.V_3 && + RootContext.MetadataCompatibilityVersion > MetadataVersion.v2) { - protected virtual void Error_TypeOrNamespaceNotFound (IResolveContext ec) - { - if (ec.CurrentType != null) { - if (ec.CurrentTypeDefinition != null) { - MemberCore mc = ec.CurrentTypeDefinition.GetDefinition (Name); - if (mc != null) { - Error_UnexpectedKind (mc, "type", GetMemberType (mc), loc); - return; - } + if (!PredefinedAttributes.Get.Dynamic.IsDefined) { + ec.Compiler.Report.Error (1980, Location, + "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?", + PredefinedAttributes.Get.Dynamic.GetSignatureForError ()); } - string ns = ec.CurrentType.Namespace; - string fullname = (ns.Length > 0) ? ns + "." + Name : Name; - foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) { - Type type = a.GetType (fullname); - if (type != null) { - Report.SymbolRelatedToPreviousError (type); - Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type)); - return; - } - } - - if (ec.CurrentTypeDefinition != null) { - Type t = ec.CurrentTypeDefinition.LookupAnyGeneric (Name); - if (t != null) { - Namespace.Error_InvalidNumberOfTypeArguments (t, loc); - return; - } - } - } - - if (targs != null) { - FullNamedExpression retval = ec.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true); - if (retval != null) { - Namespace.Error_TypeArgumentsCannotBeUsed (retval, loc); - return; - } + return new DynamicTypeExpr (loc); } - - NamespaceEntry.Error_NamespaceNotFound (loc, Name); - } - // TODO: I am still not convinced about this. If someone else will need it - // implement this as virtual property in MemberCore hierarchy - public static string GetMemberType (MemberCore mc) - { - if (mc is Property) - return "property"; - if (mc is Indexer) - return "indexer"; - if (mc is FieldBase) - return "field"; - if (mc is MethodCore) - return "method"; - if (mc is EnumMember) - return "enum"; - if (mc is Event) - return "event"; + if (silent || errors != ec.Compiler.Report.Errors) + return null; - return "type"; + Error_TypeOrNamespaceNotFound (ec); + return null; } - Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate) + Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate) { - if (in_transit) - return null; - - in_transit = true; Expression e = DoSimpleNameResolve (ec, right_side, intermediate); - in_transit = false; if (e == null) return null; @@ -2666,7 +2414,7 @@ namespace Mono.CSharp { /// Type is both an instance variable and a Type; Type.GetType /// is the static method not an instance method of type. /// - Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate) + Expression DoSimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate) { Expression e = null; @@ -2677,47 +2425,59 @@ namespace Mono.CSharp { if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ - LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc); + e = new LocalVariableReference (ec.CurrentBlock, Name, loc); + if (right_side != null) { - return var.ResolveLValue (ec, right_side); + e = e.ResolveLValue (ec, right_side); } else { - ResolveFlags rf = ResolveFlags.VariableOrValue; - if (intermediate) - rf |= ResolveFlags.DisableFlowAnalysis; - return var.Resolve (ec, rf); + if (intermediate) { + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + e = e.Resolve (ec, ResolveFlags.VariableOrValue); + } + } else { + e = e.Resolve (ec, ResolveFlags.VariableOrValue); + } } + + if (HasTypeArguments && e != null) + e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0); + + return e; } - Expression expr = current_block.Toplevel.GetParameterReference (Name, loc); - if (expr != null) { + e = current_block.Toplevel.GetParameterReference (Name, loc); + if (e != null) { if (right_side != null) - return expr.ResolveLValue (ec, right_side); + e = e.ResolveLValue (ec, right_side); + else + e = e.Resolve (ec); + + if (HasTypeArguments && e != null) + e.Error_TypeArgumentsCannotBeUsed (ec.Report, loc, null, 0); - return expr.Resolve (ec); + return e; } } // // Stage 2: Lookup members // - - Type almost_matched_type = null; - ArrayList almost_matched = null; - for (Type lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) { - e = MemberLookup (ec.CurrentType, lookup_ds, Name, loc); + int arity = HasTypeArguments ? Arity : -1; +// TypeSpec almost_matched_type = null; +// IList almost_matched = null; + for (TypeSpec lookup_ds = ec.CurrentType; lookup_ds != null; lookup_ds = lookup_ds.DeclaringType) { + e = MemberLookup (ec.Compiler, ec.CurrentType, lookup_ds, Name, arity, BindingRestriction.NoOverrides, loc); if (e != null) { PropertyExpr pe = e as PropertyExpr; if (pe != null) { - AParametersCollection param = TypeManager.GetParameterData (pe.PropertyInfo); - // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not, // it doesn't know which accessor to check permissions against - if (param.IsEmpty && pe.IsAccessibleFrom (ec.CurrentType, right_side != null)) + if (pe.PropertyInfo.Kind == MemberKind.Property && pe.IsAccessibleFrom (ec.CurrentType, right_side != null)) break; } else if (e is EventExpr) { if (((EventExpr) e).IsAccessibleFrom (ec.CurrentType)) break; - } else if (targs != null && e is TypeExpression) { + } else if (HasTypeArguments && e is TypeExpression) { e = new GenericTypeExpr (e.Type, targs, loc).ResolveAsTypeStep (ec, false); break; } else { @@ -2725,18 +2485,21 @@ namespace Mono.CSharp { } e = null; } - +/* if (almost_matched == null && almost_matched_members.Count > 0) { almost_matched_type = lookup_ds; - almost_matched = (ArrayList) almost_matched_members.Clone (); + almost_matched = new List(almost_matched_members); } +*/ } if (e == null) { +/* if (almost_matched == null && almost_matched_members.Count > 0) { almost_matched_type = ec.CurrentType; - almost_matched = (ArrayList) almost_matched_members.Clone (); + almost_matched = new List (almost_matched_members); } +*/ e = ResolveAsTypeStep (ec, true); } @@ -2749,81 +2512,46 @@ namespace Mono.CSharp { if (li != null) li.Used = true; - Error_VariableIsUsedBeforeItIsDeclared (Name); + Error_VariableIsUsedBeforeItIsDeclared (ec.Report, Name); return null; } } if (RootContext.EvalMode){ - FieldInfo fi = Evaluator.LookupField (Name); + var fi = Evaluator.LookupField (Name); if (fi != null) - return new FieldExpr (fi, loc).Resolve (ec); + return new FieldExpr (fi.Item1, loc).Resolve (ec); } - +/* if (almost_matched != null) almost_matched_members = almost_matched; if (almost_matched_type == null) almost_matched_type = ec.CurrentType; - - string type_name = ec.ResolveContext.CurrentType == null ? null : ec.ResolveContext.CurrentType.Name; - return Error_MemberLookupFailed (ec.CurrentType, null, almost_matched_type, Name, - type_name, AllMemberTypes, AllBindingFlags); +*/ + string type_name = ec.MemberContext.CurrentType == null ? null : ec.MemberContext.CurrentType.Name; + return Error_MemberLookupFailed (ec, ec.CurrentType, null, ec.CurrentType, Name, arity, + type_name, MemberKind.All, BindingRestriction.AccessibleOnly); } if (e is MemberExpr) { MemberExpr me = (MemberExpr) e; - Expression left; - if (me.IsInstance) { - if (ec.IsStatic || ec.HasAny (EmitContext.Options.FieldInitializerScope | EmitContext.Options.BaseInitializer | EmitContext.Options.ConstantScope)) { - // - // Note that an MemberExpr can be both IsInstance and IsStatic. - // An unresolved MethodGroupExpr can contain both kinds of methods - // and each predicate is true if the MethodGroupExpr contains - // at least one of that kind of method. - // - - if (!me.IsStatic && - (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) { - Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ()); - return null; - } - - // - // Pass the buck to MemberAccess and Invocation. - // - left = EmptyExpression.Null; - } else { - left = ec.GetThis (loc); - } - } else { - left = new TypeExpression (ec.CurrentType, loc); - } + // TODO: It's used by EventExpr -> FieldExpr transformation only + me = me.ResolveMemberAccess (ec, null, null); - me = me.ResolveMemberAccess (ec, left, loc, null); - if (me == null) - return null; - - if (targs != null) { + if (HasTypeArguments) { if (!targs.Resolve (ec)) return null; - me.SetTypeArguments (targs); + me.SetTypeArguments (ec, targs); } - if (!me.IsStatic && (me.InstanceExpression != null && me.InstanceExpression != EmptyExpression.Null) && - TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && - me.InstanceExpression.Type != me.DeclaringType && - !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && - (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) { - Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", - TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type)); - return null; - } + if (intermediate) + return me; return (right_side != null) ? me.DoResolveLValue (ec, right_side) - : me.DoResolve (ec); + : me.Resolve (ec); } return e; @@ -2842,17 +2570,12 @@ namespace Mono.CSharp { // resolved to different type } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - throw new NotSupportedException (); - } - - public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent) { return this; } @@ -2868,7 +2591,7 @@ namespace Mono.CSharp { /// Expression that evaluates to a type /// public abstract class TypeExpr : FullNamedExpression { - public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IMemberContext ec, bool silent) { TypeExpr t = DoResolveAsTypeStep (ec); if (t == null) @@ -2878,45 +2601,21 @@ namespace Mono.CSharp { return t; } - override public Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { return ResolveAsTypeTerminal (ec, false); } - public virtual bool CheckAccessLevel (DeclSpace ds) - { - return ds.CheckAccessLevel (Type); - } - - public virtual bool IsClass { - get { return Type.IsClass; } - } - - public virtual bool IsValueType { - get { return TypeManager.IsStruct (Type); } - } - - public virtual bool IsInterface { - get { return Type.IsInterface; } - } - - public virtual bool IsSealed { - get { return Type.IsSealed; } - } - - public virtual bool CanInheritFrom () + public virtual bool CheckAccessLevel (IMemberContext mc) { - if (Type == TypeManager.enum_type || - (Type == TypeManager.value_type && RootContext.StdLib) || - Type == TypeManager.multicast_delegate_type || - Type == TypeManager.delegate_type || - Type == TypeManager.array_type) - return false; + DeclSpace c = mc.CurrentMemberDefinition as DeclSpace; + if (c == null) + c = mc.CurrentMemberDefinition.Parent; - return true; + return c.CheckAccessLevel (Type); } - protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec); + protected abstract TypeExpr DoResolveAsTypeStep (IMemberContext ec); public override bool Equals (object obj) { @@ -2931,92 +2630,41 @@ namespace Mono.CSharp { { return Type.GetHashCode (); } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - type = storey.MutateType (type); - } } /// /// Fully resolved Expression that already evaluated to a type /// public class TypeExpression : TypeExpr { - public TypeExpression (Type t, Location l) + public TypeExpression (TypeSpec t, Location l) { Type = t; eclass = ExprClass.Type; loc = l; } - protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + protected override TypeExpr DoResolveAsTypeStep (IMemberContext ec) { return this; } - public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) + public override TypeExpr ResolveAsTypeTerminal (IMemberContext ec, bool silent) { return this; } } - // - // Used to create types from a fully qualified name. These are just used - // by the parser to setup the core types. - // - public sealed class TypeLookupExpression : TypeExpr { - readonly string ns_name; - readonly string name; - - public TypeLookupExpression (string ns, string name) - { - this.name = name; - this.ns_name = ns; - eclass = ExprClass.Type; - } - - public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) - { - // - // It's null only during mscorlib bootstrap when DefineType - // nees to resolve base type of same type - // - // For instance struct Char : IComparable - // - // TODO: it could be removed when Resolve starts to use - // DeclSpace instead of Type - // - if (type == null) { - Namespace ns = GlobalRootNamespace.Instance.GetNamespace (ns_name, false); - FullNamedExpression fne = ns.Lookup (name, loc); - if (fne != null) - type = fne.Type; - } - - return this; - } - - protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) - { - return this; - } - - public override string GetSignatureForError () - { - if (type == null) - return TypeManager.CSharpName (ns_name + "." + name, null); - - return base.GetSignatureForError (); - } - } - /// /// This class denotes an expression which evaluates to a member /// of a struct or a class. /// public abstract class MemberExpr : Expression { - protected bool is_base; + // + // An instance expression associated with this member, if it's a + // non-static member + // + public Expression InstanceExpression; /// /// The name of this member. @@ -3029,10 +2677,14 @@ namespace Mono.CSharp { // When base.member is used // public bool IsBase { - get { return is_base; } - set { is_base = value; } + get { return QueriedBaseType != null; } } + // + // A type used for base.member lookup or null + // + public TypeSpec QueriedBaseType { get; set; } + /// /// Whether this is an instance member. /// @@ -3050,95 +2702,132 @@ namespace Mono.CSharp { /// /// The type which declares this member. /// - public abstract Type DeclaringType { + public abstract TypeSpec DeclaringType { get; } - /// - /// The instance expression associated with this member, if it's a - /// non-static member. - /// - public Expression InstanceExpression; - - public static void error176 (Location loc, string name) + public static void Error_BaseAccessInExpressionTree (ResolveContext ec, Location loc) { - Report.Error (176, loc, "Static member `{0}' cannot be accessed " + - "with an instance reference, qualify it with a type name instead", name); + ec.Report.Error (831, loc, "An expression tree may not contain a base access"); } - public static void Error_BaseAccessInExpressionTree (Location loc) + // + // Converts best base candidate for virtual method starting from QueriedBaseType + // + protected MethodSpec CandidateToBaseOverride (MethodSpec method) { - Report.Error (831, loc, "An expression tree may not contain a base access"); + // + // Only when base.member is used + // + if (QueriedBaseType == null || method.DeclaringType == QueriedBaseType) + return method; + + // + // Overload resulution works on virtual or non-virtual members only (no overrides). That + // means for base.member access we have to find the closest match after we found best candidate + // + if ((method.Modifiers & Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.STATIC) != Modifiers.STATIC) { + var base_override = MemberCache.FindMember (QueriedBaseType, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec; + if (base_override != null && base_override.DeclaringType != method.DeclaringType) { + if (base_override.IsGeneric) + return base_override.MakeGenericMethod (method.TypeArguments); + + return base_override; + } + } + + return method; } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + // + // Implements identicial simple name and type-name + // + public Expression ProbeIdenticalTypeName (ResolveContext rc, Expression left, SimpleName name) { - if (InstanceExpression != null) - InstanceExpression.MutateHoistedGenericType (storey); + var t = left.Type; + if (t.Kind == MemberKind.InternalCompilerType || t is ElementTypeSpec || t.Arity > 0) + return left; + + // In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple-name is + // a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name + + if (left is MemberExpr || left is VariableReference) { + rc.Report.DisableReporting (); + Expression identical_type = rc.LookupNamespaceOrType (name.Name, 0, loc, true) as TypeExpr; + rc.Report.EnableReporting (); + if (identical_type != null && identical_type.Type == left.Type) + return identical_type; + } + + return left; } - // TODO: possible optimalization - // Cache resolved constant result in FieldBuilder <-> expression map - public virtual MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, - SimpleName original) + protected bool ResolveInstanceExpression (ResolveContext rc) { - // - // Precondition: - // original == null || original.Resolve (...) ==> left - // - - if (left is TypeExpr) { - left = left.ResolveAsBaseTerminal (ec, false); - if (left == null) - return null; + if (IsStatic) { + if (InstanceExpression != null) { + if (InstanceExpression is TypeExpr) { + ObsoleteAttribute oa = InstanceExpression.Type.GetAttributeObsolete (); + if (oa != null && !rc.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (oa, InstanceExpression.GetSignatureForError (), loc, rc.Report); + } + } else { + rc.Report.Error (176, loc, + "Static member `{0}' cannot be accessed with an instance reference, qualify it with a type name instead", + GetSignatureForError ()); + } - // TODO: Same problem as in class.cs, TypeTerminal does not - // always do all necessary checks - ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (left.Type); - if (oa != null && !ec.IsInObsoleteScope) { - AttributeTester.Report_ObsoleteMessage (oa, left.GetSignatureForError (), loc); + InstanceExpression = null; } - GenericTypeExpr ct = left as GenericTypeExpr; - if (ct != null && !ct.CheckConstraints (ec)) - return null; - // + return false; + } - if (!IsStatic) { - SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); - return null; + if (InstanceExpression == null || InstanceExpression is TypeExpr) { + if (!This.IsThisAvailable (rc, true) || InstanceExpression is TypeExpr) { + if (rc.HasSet (ResolveContext.Options.FieldInitializerScope)) + rc.Report.Error (236, loc, + "A field initializer cannot reference the nonstatic field, method, or property `{0}'", + GetSignatureForError ()); + else + rc.Report.Error (120, loc, + "An object reference is required to access non-static member `{0}'", + GetSignatureForError ()); + + return false; } - return this; - } - - if (!IsInstance) { - if (original != null && original.IdenticalNameAndTypeName (ec, left, loc)) - return this; + if (!TypeManager.IsFamilyAccessible (rc.CurrentType, DeclaringType)) { + rc.Report.Error (38, loc, + "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", + DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ()); + } - return ResolveExtensionMemberAccess (left); + InstanceExpression = rc.GetThis (loc); + return false; } - InstanceExpression = left; - return this; + var me = InstanceExpression as MemberExpr; + if (me != null) + me.ResolveInstanceExpression (rc); + + return true; } - protected virtual MemberExpr ResolveExtensionMemberAccess (Expression left) + public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) { - error176 (loc, GetSignatureForError ()); + Constant c = left as Constant; + if (c != null && c.GetValue () == null) { + ec.Report.Warning (1720, 1, left.Location, + "Expression will always cause a `{0}'", "System.NullReferenceException"); + } + + InstanceExpression = left; return this; } protected void EmitInstance (EmitContext ec, bool prepare_for_load) { - if (IsStatic) - return; - - if (InstanceExpression == EmptyExpression.Null) { - SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); - return; - } - if (TypeManager.IsValueType (InstanceExpression.Type)) { if (InstanceExpression is IMemoryLocation) { ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore); @@ -3152,13 +2841,13 @@ namespace Mono.CSharp { InstanceExpression.Emit (ec); if (prepare_for_load) - ec.ig.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Dup); } - public virtual void SetTypeArguments (TypeArguments ta) + public virtual void SetTypeArguments (ResolveContext ec, TypeArguments ta) { // TODO: need to get correct member type - Report.Error (307, loc, "The property `{0}' cannot be used with type arguments", + ec.Report.Error (307, loc, "The property `{0}' cannot be used with type arguments", GetSignatureForError ()); } } @@ -3170,10 +2859,9 @@ namespace Mono.CSharp { { readonly NamespaceEntry namespace_entry; public Expression ExtensionExpression; - Argument extension_argument; - public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l) - : base (list, extensionType, l) + public ExtensionMethodGroupExpr (List list, NamespaceEntry n, TypeSpec extensionType, Location l) + : base (list.Cast().ToList (), extensionType, l) { this.namespace_entry = n; } @@ -3186,13 +2874,7 @@ namespace Mono.CSharp { get { return namespace_entry == null; } } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - extension_argument.Expr.MutateHoistedGenericType (storey); - base.MutateHoistedGenericType (storey); - } - - public override MethodGroupExpr OverloadResolve (EmitContext ec, ref Arguments arguments, bool may_fail, Location loc) + public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, bool may_fail, Location loc) { if (arguments == null) arguments = new Arguments (1); @@ -3201,15 +2883,13 @@ namespace Mono.CSharp { MethodGroupExpr mg = ResolveOverloadExtensions (ec, ref arguments, namespace_entry, loc); // Store resolved argument and restore original arguments - if (mg != null) - ((ExtensionMethodGroupExpr)mg).extension_argument = arguments [0]; - else + if (mg == null) arguments.RemoveAt (0); // Clean-up modified arguments for error reporting return mg; } - MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc) + MethodGroupExpr ResolveOverloadExtensions (ResolveContext ec, ref Arguments arguments, NamespaceEntry ns, Location loc) { // Use normal resolve rules MethodGroupExpr mg = base.OverloadResolve (ec, ref arguments, ns != null, loc); @@ -3220,12 +2900,13 @@ namespace Mono.CSharp { return null; // Search continues - ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, loc); + int arity = type_arguments == null ? -1 : type_arguments.Count; + ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, Name, arity, loc); if (e == null) return base.OverloadResolve (ec, ref arguments, false, loc); e.ExtensionExpression = ExtensionExpression; - e.SetTypeArguments (type_arguments); + e.SetTypeArguments (ec, type_arguments); return e.ResolveOverloadExtensions (ec, ref arguments, e.namespace_entry, loc); } } @@ -3238,52 +2919,39 @@ namespace Mono.CSharp { { public interface IErrorHandler { - bool AmbiguousCall (MethodBase ambiguous); - bool NoExactMatch (EmitContext ec, MethodBase method); + bool AmbiguousCall (ResolveContext ec, MethodSpec ambiguous); + bool NoExactMatch (ResolveContext ec, MethodSpec method); } - public IErrorHandler CustomErrorHandler; - public MethodBase [] Methods; - MethodBase best_candidate; + public IErrorHandler CustomErrorHandler; + public IList Methods; + MethodSpec best_candidate; // TODO: make private public TypeArguments type_arguments; - bool identical_type_name; + SimpleName simple_name; bool has_inaccessible_candidates_only; - Type delegate_type; - Type queried_type; - - public MethodGroupExpr (MemberInfo [] mi, Type type, Location l) + TypeSpec delegate_type; + TypeSpec queried_type; + + public MethodGroupExpr (IList mi, TypeSpec type, Location l) : this (type, l) { - Methods = new MethodBase [mi.Length]; - mi.CopyTo (Methods, 0); + Methods = mi; } - public MethodGroupExpr (MemberInfo[] mi, Type type, Location l, bool inacessibleCandidatesOnly) - : this (mi, type, l) + public MethodGroupExpr (MethodSpec m, TypeSpec type, Location l) + : this (type, l) { - has_inaccessible_candidates_only = inacessibleCandidatesOnly; + Methods = new List (1) { m }; } - public MethodGroupExpr (ArrayList list, Type type, Location l) - : this (type, l) + public MethodGroupExpr (IList mi, TypeSpec type, Location l, bool inacessibleCandidatesOnly) + : this (mi, type, l) { - try { - Methods = (MethodBase[])list.ToArray (typeof (MethodBase)); - } catch { - foreach (MemberInfo m in list){ - if (!(m is MethodBase)){ - Console.WriteLine ("Name " + m.Name); - Console.WriteLine ("Found a: " + m.GetType ().FullName); - } - } - throw; - } - - + has_inaccessible_candidates_only = inacessibleCandidatesOnly; } - - protected MethodGroupExpr (Type type, Location loc) + + protected MethodGroupExpr (TypeSpec type, Location loc) { this.loc = loc; eclass = ExprClass.MethodGroup; @@ -3291,35 +2959,35 @@ namespace Mono.CSharp { queried_type = type; } - public override Type DeclaringType { + public override TypeSpec DeclaringType { get { return queried_type; } } - public Type DelegateType { - set { - delegate_type = value; + public MethodSpec BestCandidate { + get { + return best_candidate; } } - public bool IdenticalTypeName { - get { - return identical_type_name; + public TypeSpec DelegateType { + set { + delegate_type = value; } } public override string GetSignatureForError () { if (best_candidate != null) - return TypeManager.CSharpSignature (best_candidate); - - return TypeManager.CSharpSignature (Methods [0]); + return best_candidate.GetSignatureForError (); + + return Methods.First ().GetSignatureForError (); } public override string Name { get { - return Methods [0].Name; + return Methods.First ().Name; } } @@ -3328,10 +2996,6 @@ namespace Mono.CSharp { if (best_candidate != null) return !best_candidate.IsStatic; - foreach (MethodBase mb in Methods) - if (!mb.IsStatic) - return true; - return false; } } @@ -3341,22 +3005,13 @@ namespace Mono.CSharp { if (best_candidate != null) return best_candidate.IsStatic; - foreach (MethodBase mb in Methods) - if (mb.IsStatic) - return true; - return false; } } - - public static explicit operator ConstructorInfo (MethodGroupExpr mg) - { - return (ConstructorInfo)mg.best_candidate; - } - public static explicit operator MethodInfo (MethodGroupExpr mg) + public static explicit operator MethodSpec (MethodGroupExpr mg) { - return (MethodInfo)mg.best_candidate; + return mg.best_candidate; } // @@ -3365,22 +3020,22 @@ namespace Mono.CSharp { // 2 if a->q is better, // 0 if neither is better // - static int BetterExpressionConversion (EmitContext ec, Argument a, Type p, Type q) + static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q) { - Type argument_type = TypeManager.TypeToCoreType (a.Type); + TypeSpec argument_type = a.Type; if (argument_type == InternalType.AnonymousMethod && RootContext.Version > LanguageVersion.ISO_2) { // // Uwrap delegate from Expression // - if (TypeManager.DropGenericTypeArguments (p) == TypeManager.expression_type) { + if (p.GetDefinition () == TypeManager.expression_type) { p = TypeManager.GetTypeArguments (p) [0]; } - if (TypeManager.DropGenericTypeArguments (q) == TypeManager.expression_type) { + if (q.GetDefinition () == TypeManager.expression_type) { q = TypeManager.GetTypeArguments (q) [0]; } - p = Delegate.GetInvokeMethod (null, p).ReturnType; - q = Delegate.GetInvokeMethod (null, q).ReturnType; + p = Delegate.GetInvokeMethod (ec.Compiler, p).ReturnType; + q = Delegate.GetInvokeMethod (ec.Compiler, q).ReturnType; if (p == TypeManager.void_type && q != TypeManager.void_type) return 2; if (q == TypeManager.void_type && p != TypeManager.void_type) @@ -3399,7 +3054,7 @@ namespace Mono.CSharp { // // 7.4.3.4 Better conversion from type // - public static int BetterTypeConversion (EmitContext ec, Type p, Type q) + public static int BetterTypeConversion (ResolveContext ec, TypeSpec p, TypeSpec q) { if (p == null || q == null) throw new InternalErrorException ("BetterTypeConversion got a null conversion"); @@ -3418,6 +3073,9 @@ namespace Mono.CSharp { if (q == TypeManager.ushort_type || q == TypeManager.uint32_type || q == TypeManager.uint64_type) return 1; + } else if (p == InternalType.Dynamic) { + if (q == TypeManager.object_type) + return 2; } if (q == TypeManager.int32_type) { @@ -3434,6 +3092,9 @@ namespace Mono.CSharp { if (p == TypeManager.ushort_type || p == TypeManager.uint32_type || p == TypeManager.uint64_type) return 2; + } else if (q == InternalType.Dynamic) { + if (p == TypeManager.object_type) + return 1; } // TODO: this is expensive @@ -3461,12 +3122,12 @@ namespace Mono.CSharp { /// false if candidate ain't better /// true if candidate is better than the current best match /// - static bool BetterFunction (EmitContext ec, Arguments args, int argument_count, - MethodBase candidate, bool candidate_params, - MethodBase best, bool best_params) + static bool BetterFunction (ResolveContext ec, Arguments args, int argument_count, + MethodSpec candidate, bool candidate_params, + MethodSpec best, bool best_params) { - AParametersCollection candidate_pd = TypeManager.GetParameterData (candidate); - AParametersCollection best_pd = TypeManager.GetParameterData (best); + AParametersCollection candidate_pd = candidate.Parameters; + AParametersCollection best_pd = best.Parameters; bool better_at_least_one = false; bool same = true; @@ -3478,8 +3139,8 @@ namespace Mono.CSharp { if (a.IsDefaultArgument && candidate_params == best_params) return false; - Type ct = candidate_pd.Types [c_idx]; - Type bt = best_pd.Types [b_idx]; + TypeSpec ct = candidate_pd.Types [c_idx]; + TypeSpec bt = best_pd.Types [b_idx]; if (candidate_params && candidate_pd.FixedParameters [c_idx].ModFlags == Parameter.Modifier.PARAMS) { @@ -3492,8 +3153,8 @@ namespace Mono.CSharp { bt = TypeManager.GetElementType (bt); --b_idx; } - - if (ct.Equals (bt)) + + if (TypeManager.IsEqual (ct, bt)) continue; same = false; @@ -3528,10 +3189,10 @@ namespace Mono.CSharp { // // The two methods have equal parameter types. Now apply tie-breaking rules // - if (TypeManager.IsGenericMethod (best)) { - if (!TypeManager.IsGenericMethod (candidate)) + if (best.IsGeneric) { + if (!candidate.IsGeneric) return true; - } else if (TypeManager.IsGenericMethod (candidate)) { + } else if (candidate.IsGeneric) { return false; } @@ -3556,24 +3217,20 @@ namespace Mono.CSharp { return candidate_param_count > best_param_count && best_pd.HasParams; // - // now, both methods have the same number of parameters, and the parameters have the same types - // Pick the "more specific" signature + // Both methods have the same number of parameters, and the parameters have equal types + // Pick the "more specific" signature using rules over original (non-inflated) types // - - MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate); - MethodBase orig_best = TypeManager.DropGenericMethodArguments (best); - - AParametersCollection orig_candidate_pd = TypeManager.GetParameterData (orig_candidate); - AParametersCollection orig_best_pd = TypeManager.GetParameterData (orig_best); + var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters; + var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters; bool specific_at_least_once = false; for (int j = 0; j < candidate_param_count; ++j) { - Type ct = orig_candidate_pd.Types [j]; - Type bt = orig_best_pd.Types [j]; - if (ct.Equals (bt)) + var ct = candidate_def_pd.Types [j]; + var bt = best_def_pd.Types [j]; + if (ct == bt) continue; - Type specific = MoreSpecific (ct, bt); + TypeSpec specific = MoreSpecific (ct, bt); if (specific == bt) return false; if (specific == ct) @@ -3589,48 +3246,33 @@ namespace Mono.CSharp { return false; } - protected override MemberExpr ResolveExtensionMemberAccess (Expression left) - { - if (!IsStatic) - return base.ResolveExtensionMemberAccess (left); - - // - // When left side is an expression and at least one candidate method is - // static, it can be extension method - // - InstanceExpression = left; - return this; - } - - public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, - SimpleName original) + public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) { - if (!(left is TypeExpr) && - original != null && original.IdenticalNameAndTypeName (ec, left, loc)) - identical_type_name = true; + simple_name = original; - return base.ResolveMemberAccess (ec, left, loc, original); + return base.ResolveMemberAccess (ec, left, original); } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { if (best_candidate == null) { - Report.Error (1953, loc, "An expression tree cannot contain an expression with method group"); + ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group"); return null; } - IMethodData md = TypeManager.GetMethod (best_candidate); - if (md != null && md.IsExcluded ()) - Report.Error (765, loc, + if (best_candidate.IsConditionallyExcluded (loc)) + ec.Report.Error (765, loc, "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree"); return new TypeOfMethod (best_candidate, loc); } - override public Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { + this.eclass = ExprClass.MethodGroup; + if (InstanceExpression != null) { - InstanceExpression = InstanceExpression.DoResolve (ec); + InstanceExpression = InstanceExpression.Resolve (ec); if (InstanceExpression == null) return null; } @@ -3638,15 +3280,16 @@ namespace Mono.CSharp { return this; } - public void ReportUsageError () + public void ReportUsageError (ResolveContext ec) { - Report.Error (654, loc, "Method `" + DeclaringType + "." + + ec.Report.Error (654, loc, "Method `" + DeclaringType + "." + Name + "()' is referenced without parentheses"); } override public void Emit (EmitContext ec) { - ReportUsageError (); + throw new NotSupportedException (); + // ReportUsageError (); } public void EmitCall (EmitContext ec, Arguments arguments) @@ -3654,42 +3297,42 @@ namespace Mono.CSharp { Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc); } - void Error_AmbiguousCall (MethodBase ambiguous) + void Error_AmbiguousCall (ResolveContext ec, MethodSpec ambiguous) { - if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ambiguous)) + if (CustomErrorHandler != null && CustomErrorHandler.AmbiguousCall (ec, ambiguous)) return; - Report.SymbolRelatedToPreviousError (best_candidate); - Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", - TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate)); + ec.Report.SymbolRelatedToPreviousError (best_candidate); + ec.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", + best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ()); } - protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method, - Argument a, AParametersCollection expected_par, Type paramType) + protected virtual void Error_InvalidArguments (ResolveContext ec, Location loc, int idx, MethodSpec method, + Argument a, AParametersCollection expected_par, TypeSpec paramType) { ExtensionMethodGroupExpr emg = this as ExtensionMethodGroupExpr; if (a is CollectionElementInitializer.ElementInitializerArgument) { - Report.SymbolRelatedToPreviousError (method); + ec.Report.SymbolRelatedToPreviousError (method); if ((expected_par.FixedParameters [idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) { - Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier", + ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier", TypeManager.CSharpSignature (method)); return; } - Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments", + ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments", TypeManager.CSharpSignature (method)); } else if (TypeManager.IsDelegateType (method.DeclaringType)) { - Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", + ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", TypeManager.CSharpName (method.DeclaringType)); } else { - Report.SymbolRelatedToPreviousError (method); + ec.Report.SymbolRelatedToPreviousError (method); if (emg != null) { - Report.Error (1928, loc, + ec.Report.Error (1928, loc, "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments", emg.ExtensionExpression.GetSignatureForError (), emg.Name, TypeManager.CSharpSignature (method)); } else { - Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", + ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", TypeManager.CSharpSignature (method)); } } @@ -3700,53 +3343,69 @@ namespace Mono.CSharp { if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^ (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) { if ((mod & Parameter.Modifier.ISBYREF) == 0) - Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier", + ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier", index, Parameter.GetModifierSignature (a.Modifier)); else - Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier", + ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier", index, Parameter.GetModifierSignature (mod)); } else { string p1 = a.GetSignatureForError (); string p2 = TypeManager.CSharpName (paramType); if (p1 == p2) { - Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous "); - Report.SymbolRelatedToPreviousError (a.Expr.Type); - Report.SymbolRelatedToPreviousError (paramType); + ec.Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous "); + ec.Report.SymbolRelatedToPreviousError (a.Expr.Type); + ec.Report.SymbolRelatedToPreviousError (paramType); } if (idx == 0 && emg != null) { - Report.Error (1929, loc, + ec.Report.Error (1929, loc, "Extension method instance type `{0}' cannot be converted to `{1}'", p1, p2); } else { - Report.Error (1503, loc, + ec.Report.Error (1503, loc, "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2); } } } - public override void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) { - Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", + ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", Name, TypeManager.CSharpName (target)); } - void Error_ArgumentCountWrong (int arg_count) + void Error_ArgumentCountWrong (ResolveContext ec, int arg_count) { - Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", + ec.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", Name, arg_count.ToString ()); } - protected virtual int GetApplicableParametersCount (MethodBase method, AParametersCollection parameters) + protected virtual int GetApplicableParametersCount (MethodSpec method, AParametersCollection parameters) { return parameters.Count; - } + } + + protected virtual IList GetBaseTypeMethods (ResolveContext rc, TypeSpec type) + { + var arity = type_arguments == null ? -1 : type_arguments.Count; - public static bool IsAncestralType (Type first_type, Type second_type) + return TypeManager.MemberLookup (rc.CurrentType, null, type, + MemberKind.Method, BindingRestriction.AccessibleOnly | BindingRestriction.NoOverrides, + Name, arity, null); + } + + bool GetBaseTypeMethods (ResolveContext rc) { - return first_type != second_type && - (TypeManager.IsSubclassOf (second_type, first_type) || - TypeManager.ImplementsInterface (second_type, first_type)); + var base_type = Methods [0].DeclaringType.BaseType; + if (base_type == null) + return false; + + var methods = GetBaseTypeMethods (rc, base_type); + if (methods == null) + return false; + + Methods = methods; + return true; } /// @@ -3755,12 +3414,12 @@ namespace Mono.CSharp { /// A return value rates candidate method compatibility, /// 0 = the best, int.MaxValue = the worst /// - public int IsApplicable (EmitContext ec, - ref Arguments arguments, int arg_count, ref MethodBase method, ref bool params_expanded_form) + public int IsApplicable (ResolveContext ec, + ref Arguments arguments, int arg_count, ref MethodSpec method, ref bool params_expanded_form) { - MethodBase candidate = method; + var candidate = method; - AParametersCollection pd = TypeManager.GetParameterData (candidate); + AParametersCollection pd = candidate.Parameters; int param_count = GetApplicableParametersCount (candidate, pd); int optional_count = 0; @@ -3772,7 +3431,7 @@ namespace Mono.CSharp { } } - int args_gap = Math.Abs (arg_count - param_count); + int args_gap = System.Math.Abs (arg_count - param_count); if (optional_count != 0) { if (args_gap > optional_count) return int.MaxValue - 10000 + args_gap - optional_count; @@ -3782,6 +3441,8 @@ namespace Mono.CSharp { optional_count--; if (arg_count < param_count) param_count--; + } else if (arg_count > param_count) { + return int.MaxValue - 10000 + args_gap; } } else if (arg_count != param_count) { if (!pd.HasParams) @@ -3823,7 +3484,7 @@ namespace Mono.CSharp { if (na == null) break; - int index = pd.GetParameterIndexByName (na.Name.Value); + int index = pd.GetParameterIndexByName (na.Name); // Named parameter not found or already reordered if (index <= i) @@ -3853,43 +3514,36 @@ namespace Mono.CSharp { arg_count = arguments.Count; } -#if GMCS_SOURCE // // 1. Handle generic method using type arguments when specified or type inference // - if (TypeManager.IsGenericMethod (candidate)) { + if (candidate.IsGeneric) { if (type_arguments != null) { - Type [] g_args = candidate.GetGenericArguments (); - if (g_args.Length != type_arguments.Count) - return int.MaxValue - 20000 + Math.Abs (type_arguments.Count - g_args.Length); + var g_args_count = candidate.Arity; + if (g_args_count != type_arguments.Count) + return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count); - // TODO: Don't create new method, create Parameters only - method = ((MethodInfo) candidate).MakeGenericMethod (type_arguments.Arguments); + method = candidate.MakeGenericMethod (type_arguments.Arguments); candidate = method; - pd = TypeManager.GetParameterData (candidate); + pd = candidate.Parameters; } else { int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate); if (score != 0) return score - 20000; - if (TypeManager.IsGenericMethodDefinition (candidate)) - throw new InternalErrorException ("A generic method `{0}' definition took part in overload resolution", - TypeManager.CSharpSignature (candidate)); - - pd = TypeManager.GetParameterData (candidate); + pd = candidate.Parameters; } } else { if (type_arguments != null) return int.MaxValue - 15000; } -#endif // // 2. Each argument has to be implicitly convertible to method parameter // method = candidate; Parameter.Modifier p_mod = 0; - Type pt = null; + TypeSpec pt = null; for (int i = 0; i < arg_count; i++) { Argument a = arguments [i]; if (a == null) { @@ -3936,7 +3590,7 @@ namespace Mono.CSharp { return 0; } - int IsArgumentCompatible (EmitContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, Type parameter) + int IsArgumentCompatible (ResolveContext ec, Parameter.Modifier arg_mod, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter) { // // Types have to be identical when ref or out modifer is used @@ -3945,15 +3599,23 @@ namespace Mono.CSharp { if (TypeManager.HasElementType (parameter)) parameter = TypeManager.GetElementType (parameter); - Type a_type = argument.Type; + TypeSpec a_type = argument.Type; if (TypeManager.HasElementType (a_type)) a_type = TypeManager.GetElementType (a_type); - if (a_type != parameter) + if (a_type != parameter) { + if (a_type == InternalType.Dynamic) + return 0; + return 2; + } } else { - if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) + if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) { + if (argument.Type == InternalType.Dynamic) + return 0; + return 2; + } } if (arg_mod != param_mod) @@ -3962,31 +3624,6 @@ namespace Mono.CSharp { return 0; } - public static bool IsOverride (MethodBase cand_method, MethodBase base_method) - { - if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType)) - return false; - - AParametersCollection cand_pd = TypeManager.GetParameterData (cand_method); - AParametersCollection base_pd = TypeManager.GetParameterData (base_method); - - if (cand_pd.Count != base_pd.Count) - return false; - - for (int j = 0; j < cand_pd.Count; ++j) - { - Parameter.Modifier cm = cand_pd.FixedParameters [j].ModFlags; - Parameter.Modifier bm = base_pd.FixedParameters [j].ModFlags; - Type ct = cand_pd.Types [j]; - Type bt = base_pd.Types [j]; - - if (cm != bm || ct != bt) - return false; - } - - return true; - } - public static MethodGroupExpr MakeUnionSet (MethodGroupExpr mg1, MethodGroupExpr mg2, Location loc) { if (mg1 == null) { @@ -3997,47 +3634,43 @@ namespace Mono.CSharp { if (mg2 == null) return mg1; - - ArrayList all = new ArrayList (mg1.Methods); - foreach (MethodBase m in mg2.Methods){ - if (!TypeManager.ArrayContainsMethod (mg1.Methods, m, false)) + + var all = new List (mg1.Methods); + foreach (MethodSpec m in mg2.Methods){ + if (!TypeManager.ArrayContainsMethod (all, m, false)) all.Add (m); } return new MethodGroupExpr (all, null, loc); } - static Type MoreSpecific (Type p, Type q) + static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q) { if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q)) return q; if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q)) return p; - if (TypeManager.HasElementType (p)) - { - Type pe = TypeManager.GetElementType (p); - Type qe = TypeManager.GetElementType (q); - Type specific = MoreSpecific (pe, qe); - if (specific == pe) + var ac_p = p as ArrayContainer; + if (ac_p != null) { + var ac_q = ((ArrayContainer) q); + TypeSpec specific = MoreSpecific (ac_p.Element, (ac_q.Element)); + if (specific == ac_p.Element) return p; - if (specific == qe) + if (specific == ac_q.Element) return q; - } - else if (TypeManager.IsGenericType (p)) - { - Type[] pargs = TypeManager.GetTypeArguments (p); - Type[] qargs = TypeManager.GetTypeArguments (q); + } else if (TypeManager.IsGenericType (p)) { + var pargs = TypeManager.GetTypeArguments (p); + var qargs = TypeManager.GetTypeArguments (q); bool p_specific_at_least_once = false; bool q_specific_at_least_once = false; - for (int i = 0; i < pargs.Length; i++) - { - Type specific = MoreSpecific (TypeManager.TypeToCoreType (pargs [i]), TypeManager.TypeToCoreType (qargs [i])); - if (specific == pargs [i]) + for (int i = 0; i < pargs.Length; i++) { + TypeSpec specific = MoreSpecific (pargs[i], qargs[i]); + if (specific == pargs[i]) p_specific_at_least_once = true; - if (specific == qargs [i]) + if (specific == qargs[i]) q_specific_at_least_once = true; } @@ -4050,19 +3683,6 @@ namespace Mono.CSharp { return null; } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) - { - base.MutateHoistedGenericType (storey); - - MethodInfo mi = best_candidate as MethodInfo; - if (mi != null) { - best_candidate = storey.MutateGenericMethod (mi); - return; - } - - best_candidate = storey.MutateConstructor ((ConstructorInfo) this); - } - /// /// Find the Applicable Function Members (7.4.2.1) /// @@ -4079,150 +3699,114 @@ namespace Mono.CSharp { /// that is the best match of me on Arguments. /// /// - public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ref Arguments Arguments, + public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments, bool may_fail, Location loc) { - bool method_params = false; - Type applicable_type = null; - ArrayList candidates = new ArrayList (2); - ArrayList candidate_overrides = null; - - // - // Used to keep a map between the candidate - // and whether it is being considered in its - // normal or expanded form - // - // false is normal form, true is expanded form - // - Hashtable candidate_to_form = null; - Hashtable candidates_expanded = null; - Arguments candidate_args = Arguments; + var candidates = new List (2); + List params_candidates = null; int arg_count = Arguments != null ? Arguments.Count : 0; + Dictionary candidates_expanded = null; + Arguments candidate_args = Arguments; if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) { if (!may_fail) - Report.Error (1533, loc, "Invoke cannot be called directly on a delegate"); + ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate"); return null; } - int nmethods = Methods.Length; - - if (!IsBase) { - // - // Methods marked 'override' don't take part in 'applicable_type' - // computation, nor in the actual overload resolution. - // However, they still need to be emitted instead of a base virtual method. - // So, we salt them away into the 'candidate_overrides' array. - // - // In case of reflected methods, we replace each overriding method with - // its corresponding base virtual method. This is to improve compatibility - // with non-C# libraries which change the visibility of overrides (#75636) - // - int j = 0; - for (int i = 0; i < Methods.Length; ++i) { - MethodBase m = Methods [i]; - if (TypeManager.IsOverride (m)) { - if (candidate_overrides == null) - candidate_overrides = new ArrayList (); - candidate_overrides.Add (m); - m = TypeManager.TryGetBaseDefinition (m); - } - if (m != null) - Methods [j++] = m; - } - nmethods = j; - } - // // Enable message recording, it's used mainly by lambda expressions // - Report.IMessageRecorder msg_recorder = new Report.MessageRecorder (); - Report.IMessageRecorder prev_recorder = Report.SetMessageRecorder (msg_recorder); - - // - // First we construct the set of applicable methods - // - bool is_sorted = true; - int best_candidate_rate = int.MaxValue; - for (int i = 0; i < nmethods; i++) { - Type decl_type = Methods [i].DeclaringType; + var msg_recorder = new SessionReportPrinter (); + var prev_recorder = ec.Report.SetPrinter (msg_recorder); + try { + do { + // + // Methods in a base class are not candidates if any method in a derived + // class is applicable + // + int best_candidate_rate = int.MaxValue; + + foreach (var member in Methods) { + var m = member as MethodSpec; + if (m == null) { + // TODO: It's wrong when non-member is before applicable method + // TODO: Should report only when at least 1 from the batch is applicable + if (candidates.Count != 0) { + ec.Report.SymbolRelatedToPreviousError (candidates[0]); + ec.Report.SymbolRelatedToPreviousError (member); + ec.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'", + candidates[0].GetSignatureForError (), member.GetSignatureForError ()); + } + continue; + } - // - // If we have already found an applicable method - // we eliminate all base types (Section 14.5.5.1) - // - if (applicable_type != null && IsAncestralType (decl_type, applicable_type)) - continue; + // + // Check if candidate is applicable (section 14.4.2.1) + // + bool params_expanded_form = false; + int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref m, ref params_expanded_form); - // - // Check if candidate is applicable (section 14.4.2.1) - // - bool params_expanded_form = false; - int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form); + if (candidate_rate < best_candidate_rate) { + best_candidate_rate = candidate_rate; + best_candidate = m; + } - if (candidate_rate < best_candidate_rate) { - best_candidate_rate = candidate_rate; - best_candidate = Methods [i]; - } - - if (params_expanded_form) { - if (candidate_to_form == null) - candidate_to_form = new PtrHashtable (); - MethodBase candidate = Methods [i]; - candidate_to_form [candidate] = candidate; - } - - if (candidate_args != Arguments) { - if (candidates_expanded == null) - candidates_expanded = new Hashtable (2); + if (params_expanded_form) { + if (params_candidates == null) + params_candidates = new List (2); + params_candidates.Add (m); + } - candidates_expanded.Add (Methods [i], candidate_args); - candidate_args = Arguments; - } + if (candidate_args != Arguments) { + if (candidates_expanded == null) + candidates_expanded = new Dictionary (2); - if (candidate_rate != 0 || has_inaccessible_candidates_only) { - if (msg_recorder != null) - msg_recorder.EndSession (); - continue; - } + candidates_expanded.Add (m, candidate_args); + candidate_args = Arguments; + } - msg_recorder = null; - candidates.Add (Methods [i]); + if (candidate_rate != 0 || has_inaccessible_candidates_only) { + if (msg_recorder != null) + msg_recorder.EndSession (); + continue; + } - if (applicable_type == null) - applicable_type = decl_type; - else if (applicable_type != decl_type) { - is_sorted = false; - if (IsAncestralType (applicable_type, decl_type)) - applicable_type = decl_type; - } + msg_recorder = null; + candidates.Add (m); + } + } while (candidates.Count == 0 && GetBaseTypeMethods (ec)); + } finally { + ec.Report.SetPrinter (prev_recorder); } - Report.SetMessageRecorder (prev_recorder); - if (msg_recorder != null && !msg_recorder.IsEmpty) { - if (!may_fail) - msg_recorder.PrintMessages (); - - return null; - } - int candidate_top = candidates.Count; - - if (applicable_type == null) { + if (candidate_top == 0) { // // When we found a top level method which does not match and it's // not an extension method. We start extension methods lookup from here // if (InstanceExpression != null) { - ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc); + var first = Methods.First (); + var arity = type_arguments == null ? -1 : type_arguments.Count; + ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, first.Name, arity, loc); if (ex_method_lookup != null) { - ex_method_lookup.ExtensionExpression = InstanceExpression; - ex_method_lookup.SetTypeArguments (type_arguments); - return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc); + ex_method_lookup.ExtensionExpression = InstanceExpression.Resolve (ec); + ex_method_lookup.SetTypeArguments (ec, type_arguments); + var emg = ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc); + if (emg != null) + return emg; } } - + + if (msg_recorder != null && !msg_recorder.IsEmpty) { + if (!may_fail) + msg_recorder.Merge (prev_recorder); + + return null; + } + if (may_fail) return null; @@ -4234,146 +3818,49 @@ namespace Mono.CSharp { if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate)) return null; - AParametersCollection pd = TypeManager.GetParameterData (best_candidate); - bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate); - if (arg_count == pd.Count || pd.HasParams) { - if (TypeManager.IsGenericMethodDefinition (best_candidate)) { - if (type_arguments == null) { - Report.Error (411, loc, - "The type arguments for method `{0}' cannot be inferred from " + - "the usage. Try specifying the type arguments explicitly", - TypeManager.CSharpSignature (best_candidate)); - return null; - } - - Type[] g_args = TypeManager.GetGenericArguments (best_candidate); - if (type_arguments.Count != g_args.Length) { - Report.SymbolRelatedToPreviousError (best_candidate); - Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)", - TypeManager.CSharpSignature (best_candidate), - g_args.Length.ToString ()); - return null; - } - } else { - if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) { - Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc); - return null; - } - } - - if (has_inaccessible_candidates_only) { - if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) { - // Although a derived class can access protected members of - // its base class it cannot do so through an instance of the - // base class (CS1540). If the qualifier_type is a base of the - // ec.CurrentType and the lookup succeeds with the latter one, - // then we are in this situation. - Error_CannotAccessProtected (loc, best_candidate, queried_type, ec.CurrentType); - } else { - Report.SymbolRelatedToPreviousError (best_candidate); - ErrorIsInaccesible (loc, GetSignatureForError ()); - } - } - - if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc)) - return null; - - if (has_inaccessible_candidates_only) - return null; - - throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate); - } + bool params_expanded = params_candidates != null && params_candidates.Contains (best_candidate); + if (NoExactMatch (ec, ref Arguments, params_expanded)) + return null; } // // We failed to find any method with correct argument count // - if (Name == ConstructorInfo.ConstructorName) { - Report.SymbolRelatedToPreviousError (queried_type); - Report.Error (1729, loc, + if (Methods.First ().Kind == MemberKind.Constructor) { + ec.Report.SymbolRelatedToPreviousError (queried_type); + ec.Report.Error (1729, loc, "The type `{0}' does not contain a constructor that takes `{1}' arguments", - TypeManager.CSharpName (queried_type), arg_count); + TypeManager.CSharpName (queried_type), arg_count.ToString ()); } else { - Error_ArgumentCountWrong (arg_count); + Error_ArgumentCountWrong (ec, arg_count); } return null; } - if (!is_sorted) { - // - // At this point, applicable_type is _one_ of the most derived types - // in the set of types containing the methods in this MethodGroup. - // Filter the candidates so that they only contain methods from the - // most derived types. - // - - int finalized = 0; // Number of finalized candidates - - do { - // Invariant: applicable_type is a most derived type - - // We'll try to complete Section 14.5.5.1 for 'applicable_type' by - // eliminating all it's base types. At the same time, we'll also move - // every unrelated type to the end of the array, and pick the next - // 'applicable_type'. - - Type next_applicable_type = null; - int j = finalized; // where to put the next finalized candidate - int k = finalized; // where to put the next undiscarded candidate - for (int i = finalized; i < candidate_top; ++i) { - MethodBase candidate = (MethodBase) candidates [i]; - Type decl_type = candidate.DeclaringType; - - if (decl_type == applicable_type) { - candidates [k++] = candidates [j]; - candidates [j++] = candidates [i]; - continue; - } - - if (IsAncestralType (decl_type, applicable_type)) - continue; - - if (next_applicable_type != null && - IsAncestralType (decl_type, next_applicable_type)) - continue; - - candidates [k++] = candidates [i]; - - if (next_applicable_type == null || - IsAncestralType (next_applicable_type, decl_type)) - next_applicable_type = decl_type; - } - - applicable_type = next_applicable_type; - finalized = j; - candidate_top = k; - } while (applicable_type != null); + if (arg_count != 0 && Arguments.HasDynamic) { + best_candidate = null; + return this; } // // Now we actually find the best method // - - best_candidate = (MethodBase) candidates [0]; - method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate); - - // - // TODO: Broken inverse order of candidates logic does not work with optional - // parameters used for method overrides and I am not going to fix it for SRE - // - if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) { - candidate_args = (Arguments) candidates_expanded [best_candidate]; - arg_count = candidate_args.Count; - } + best_candidate = candidates [0]; + bool method_params = params_candidates != null && params_candidates.Contains (best_candidate); for (int ix = 1; ix < candidate_top; ix++) { - MethodBase candidate = (MethodBase) candidates [ix]; + var candidate = candidates [ix]; if (candidate == best_candidate) continue; - bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); + bool cand_params = params_candidates != null && params_candidates.Contains (candidate); + + if (candidates_expanded != null && candidates_expanded.ContainsKey (candidate)) { + candidate_args = candidates_expanded[candidate]; + arg_count = candidate_args.Count; + } if (BetterFunction (ec, candidate_args, arg_count, candidate, cand_params, @@ -4381,73 +3868,47 @@ namespace Mono.CSharp { best_candidate = candidate; method_params = cand_params; } + + if (candidate_args != Arguments) { + candidate_args = Arguments; + arg_count = candidate_args != null ? candidate_args.Count : 0; + } + } + + if (candidates_expanded != null && candidates_expanded.ContainsKey (best_candidate)) { + candidate_args = candidates_expanded[best_candidate]; + arg_count = candidate_args.Count; } + // // Now check that there are no ambiguities i.e the selected method // should be better than all the others // - MethodBase ambiguous = null; + MethodSpec ambiguous = null; for (int ix = 1; ix < candidate_top; ix++) { - MethodBase candidate = (MethodBase) candidates [ix]; + var candidate = candidates [ix]; if (candidate == best_candidate) continue; - bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); + bool cand_params = params_candidates != null && params_candidates.Contains (candidate); if (!BetterFunction (ec, candidate_args, arg_count, best_candidate, method_params, candidate, cand_params)) { if (!may_fail) - Report.SymbolRelatedToPreviousError (candidate); + ec.Report.SymbolRelatedToPreviousError (candidate); ambiguous = candidate; } } if (ambiguous != null) { - Error_AmbiguousCall (ambiguous); + Error_AmbiguousCall (ec, ambiguous); return this; } - // - // If the method is a virtual function, pick an override closer to the LHS type. - // - if (!IsBase && best_candidate.IsVirtual) { - if (TypeManager.IsOverride (best_candidate)) - throw new InternalErrorException ( - "Should not happen. An 'override' method took part in overload resolution: " + best_candidate); - - if (candidate_overrides != null) { - Type[] gen_args = null; - bool gen_override = false; - if (TypeManager.IsGenericMethod (best_candidate)) - gen_args = TypeManager.GetGenericArguments (best_candidate); - - foreach (MethodBase candidate in candidate_overrides) { - if (TypeManager.IsGenericMethod (candidate)) { - if (gen_args == null) - continue; - - if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length) - continue; - } else { - if (gen_args != null) - continue; - } - - if (IsOverride (candidate, best_candidate)) { - gen_override = true; - best_candidate = candidate; - } - } - - if (gen_override && gen_args != null) { -#if GMCS_SOURCE - best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args); -#endif - } - } - } + if (IsBase) + best_candidate = CandidateToBaseOverride (best_candidate); // // And now check if the arguments are all @@ -4462,46 +3923,101 @@ namespace Mono.CSharp { if (best_candidate == null) return null; - MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate); - if (TypeManager.IsGenericMethodDefinition (the_method) && - !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc)) - return null; + if (best_candidate.Kind == MemberKind.Method) { + if (InstanceExpression != null) { + if (best_candidate.IsStatic) { + InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name); + } + + InstanceExpression.Resolve (ec); + } + + ResolveInstanceExpression (ec); + } + + if (best_candidate.IsGeneric) { + ConstraintChecker.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments, + best_candidate.Constraints, loc, ec.Report); + } // // Check ObsoleteAttribute on the best method // - ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method); - if (oa != null && !ec.IsInObsoleteScope) - AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); + ObsoleteAttribute oa = best_candidate.GetAttributeObsolete (); + if (oa != null && !ec.IsObsolete) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); - IMethodData data = TypeManager.GetMethod (the_method); - if (data != null) - data.SetMemberIsUsed (); + best_candidate.MemberDefinition.SetIsUsed (); Arguments = candidate_args; return this; } + + bool NoExactMatch (ResolveContext ec, ref Arguments Arguments, bool params_expanded) + { + AParametersCollection pd = best_candidate.Parameters; + int arg_count = Arguments == null ? 0 : Arguments.Count; + + if (arg_count == pd.Count || pd.HasParams) { + if (best_candidate.IsGeneric) { + if (type_arguments == null) { + ec.Report.Error (411, loc, + "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly", + best_candidate.GetGenericMethodDefinition().GetSignatureForError ()); + return true; + } + } + + var ta = type_arguments == null ? 0 : type_arguments.Count; + if (ta != best_candidate.Arity) { + Error_TypeArgumentsCannotBeUsed (ec.Report, loc, best_candidate, type_arguments.Count); + return true; + } + + if (has_inaccessible_candidates_only) { + if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) { + // Although a derived class can access protected members of + // its base class it cannot do so through an instance of the + // base class (CS1540). If the qualifier_type is a base of the + // ec.CurrentType and the lookup succeeds with the latter one, + // then we are in this situation. + Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType); + } else { + ec.Report.SymbolRelatedToPreviousError (best_candidate); + ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report); + } + } + + if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, params_expanded, false, loc)) + return true; + + if (has_inaccessible_candidates_only) + return true; + } + + return false; + } - public override void SetTypeArguments (TypeArguments ta) + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) { type_arguments = ta; } - public bool VerifyArgumentsCompat (EmitContext ec, ref Arguments arguments, - int arg_count, MethodBase method, + public bool VerifyArgumentsCompat (ResolveContext ec, ref Arguments arguments, + int arg_count, MethodSpec method, bool chose_params_expanded, bool may_fail, Location loc) { - AParametersCollection pd = TypeManager.GetParameterData (method); + AParametersCollection pd = method.Parameters; int param_count = GetApplicableParametersCount (method, pd); - int errors = Report.Errors; + int errors = ec.Report.Errors; Parameter.Modifier p_mod = 0; - Type pt = null; + TypeSpec pt = null; int a_idx = 0, a_pos = 0; Argument a = null; - ArrayList params_initializers = null; - bool has_unsafe_arg = false; + ArrayInitializer params_initializers = null; + bool has_unsafe_arg = method.ReturnType.IsPointer; for (; a_idx < arg_count; a_idx++, ++a_pos) { a = arguments [a_idx]; @@ -4512,7 +4028,7 @@ namespace Mono.CSharp { if (p_mod == Parameter.Modifier.PARAMS) { if (chose_params_expanded) { - params_initializers = new ArrayList (arg_count - a_idx); + params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location); pt = TypeManager.GetElementType (pt); } } @@ -4532,32 +4048,35 @@ namespace Mono.CSharp { } else { NamedArgument na = a as NamedArgument; if (na != null) { - int name_index = pd.GetParameterIndexByName (na.Name.Value); + int name_index = pd.GetParameterIndexByName (na.Name); if (name_index < 0 || name_index >= param_count) { if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) { - Report.SymbolRelatedToPreviousError (DeclaringType); - Report.Error (1746, na.Name.Location, + ec.Report.SymbolRelatedToPreviousError (DeclaringType); + ec.Report.Error (1746, na.Location, "The delegate `{0}' does not contain a parameter named `{1}'", - TypeManager.CSharpName (DeclaringType), na.Name.Value); + TypeManager.CSharpName (DeclaringType), na.Name); } else { - Report.SymbolRelatedToPreviousError (best_candidate); - Report.Error (1739, na.Name.Location, + ec.Report.SymbolRelatedToPreviousError (best_candidate); + ec.Report.Error (1739, na.Location, "The best overloaded method match for `{0}' does not contain a parameter named `{1}'", - TypeManager.CSharpSignature (method), na.Name.Value); + TypeManager.CSharpSignature (method), na.Name); } } else if (arguments[name_index] != a) { if (DeclaringType != null && TypeManager.IsDelegateType (DeclaringType)) - Report.SymbolRelatedToPreviousError (DeclaringType); + ec.Report.SymbolRelatedToPreviousError (DeclaringType); else - Report.SymbolRelatedToPreviousError (best_candidate); + ec.Report.SymbolRelatedToPreviousError (best_candidate); - Report.Error (1744, na.Name.Location, + ec.Report.Error (1744, na.Location, "Named argument `{0}' cannot be used for a parameter which has positional argument specified", - na.Name.Value); + na.Name); } } } + if (a.Expr.Type == InternalType.Dynamic) + continue; + if (delegate_type != null && !Delegate.IsTypeCovariant (a.Expr, pt)) break; @@ -4582,7 +4101,7 @@ namespace Mono.CSharp { } if (a_idx != arg_count) { - if (!may_fail && Report.Errors == errors) { + if (!may_fail && ec.Report.Errors == errors) { if (CustomErrorHandler != null) CustomErrorHandler.NoExactMatch (ec, best_candidate); else @@ -4601,7 +4120,7 @@ namespace Mono.CSharp { pt = pd.Types [param_count - 1]; pt = TypeManager.GetElementType (pt); has_unsafe_arg |= pt.IsPointer; - params_initializers = new ArrayList (0); + params_initializers = new ArrayInitializer (0, loc); } // @@ -4609,20 +4128,19 @@ namespace Mono.CSharp { // if (params_initializers != null) { arguments.Add (new Argument ( - new ArrayCreation (new TypeExpression (pt, loc), "[]", - params_initializers, loc).Resolve (ec))); + new ArrayCreation (new TypeExpression (pt, loc), params_initializers, loc).Resolve (ec))); arg_count++; } if (arg_count < param_count) { if (!may_fail) - Error_ArgumentCountWrong (arg_count); + Error_ArgumentCountWrong (ec, arg_count); return false; } - if (has_unsafe_arg && !ec.InUnsafe) { + if (has_unsafe_arg && !ec.IsUnsafe) { if (!may_fail) - UnsafeError (loc); + UnsafeError (ec, loc); return false; } @@ -4632,9 +4150,9 @@ namespace Mono.CSharp { public class ConstantExpr : MemberExpr { - FieldInfo constant; + ConstSpec constant; - public ConstantExpr (FieldInfo constant, Location loc) + public ConstantExpr (ConstSpec constant, Location loc) { this.constant = constant; this.loc = loc; @@ -4649,47 +4167,35 @@ namespace Mono.CSharp { } public override bool IsStatic { - get { return constant.IsStatic; } + get { return true; } } - public override Type DeclaringType { + public override TypeSpec DeclaringType { get { return constant.DeclaringType; } } - public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, SimpleName original) - { - constant = TypeManager.GetGenericFieldDefinition (constant); - - IConstant ic = TypeManager.GetConstant (constant); - if (ic == null) { - if (constant.IsLiteral) { - ic = new ExternalConstant (constant); - } else { - ic = ExternalConstant.CreateDecimal (constant); - // HACK: decimal field was not resolved as constant - if (ic == null) - return new FieldExpr (constant, loc).ResolveMemberAccess (ec, left, loc, original); - } - TypeManager.RegisterConstant (constant, ic); - } - - return base.ResolveMemberAccess (ec, left, loc, original); - } - - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext rc) { - IConstant ic = TypeManager.GetConstant (constant); - if (ic.ResolveValue ()) { - if (!ec.IsInObsoleteScope) - ic.CheckObsoleteness (loc); + constant.MemberDefinition.SetIsUsed (); + + ResolveInstanceExpression (rc); + + if (!rc.IsObsolete) { + var oa = constant.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (constant), loc, rc.Report); } - return ic.CreateConstantReference (loc); + // Constants are resolved on-demand + var c = constant.Value.Resolve (rc) as Constant; + + // Creates reference expression to the constant value + return Constant.CreateConstant (rc, constant.MemberType, c.GetValue (), loc); } public override void Emit (EmitContext ec) @@ -4706,9 +4212,8 @@ namespace Mono.CSharp { /// /// Fully resolved expression that evaluates to a Field /// - public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariableReference { - public FieldInfo FieldInfo; - readonly Type constructed_generic_type; + public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference { + protected FieldSpec spec; VariableInfo variable_info; LocalTemporary temp; @@ -4718,49 +4223,53 @@ namespace Mono.CSharp { { loc = l; } - - public FieldExpr (FieldInfo fi, Location l) + + public FieldExpr (FieldSpec spec, Location loc) { - FieldInfo = fi; - type = TypeManager.TypeToCoreType (fi.FieldType); - loc = l; - } + this.spec = spec; + this.loc = loc; - public FieldExpr (FieldInfo fi, Type genericType, Location l) - : this (fi, l) + type = spec.MemberType; + } + + public FieldExpr (FieldBase fi, Location l) + : this (fi.Spec, l) { - if (TypeManager.IsGenericTypeDefinition (genericType)) - return; - this.constructed_generic_type = genericType; } public override string Name { get { - return FieldInfo.Name; + return spec.Name; } } public override bool IsInstance { get { - return !FieldInfo.IsStatic; + return !spec.IsStatic; } } public override bool IsStatic { get { - return FieldInfo.IsStatic; + return spec.IsStatic; + } + } + + public FieldSpec Spec { + get { + return spec; } } - public override Type DeclaringType { + public override TypeSpec DeclaringType { get { - return FieldInfo.DeclaringType; + return spec.DeclaringType; } } public override string GetSignatureForError () { - return TypeManager.GetFullNameSignature (FieldInfo); + return TypeManager.GetFullNameSignature (spec); } public VariableInfo VariableInfo { @@ -4769,19 +4278,6 @@ namespace Mono.CSharp { } } - public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, - SimpleName original) - { - FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo); - Type t = fi.FieldType; - - if (t.IsPointer && !ec.InUnsafe) { - UnsafeError (loc); - } - - return base.ResolveMemberAccess (ec, left, loc, original); - } - public void SetHasAddressTaken () { IVariableReference vr = InstanceExpression as IVariableReference; @@ -4789,7 +4285,7 @@ namespace Mono.CSharp { vr.SetHasAddressTaken (); } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { Expression instance; if (InstanceExpression == null) { @@ -4802,88 +4298,76 @@ namespace Mono.CSharp { instance, CreateTypeOfExpression ()); - return CreateExpressionFactoryCall ("Field", args); + return CreateExpressionFactoryCall (ec, "Field", args); } public Expression CreateTypeOfExpression () { - return new TypeOfField (GetConstructedFieldInfo (), loc); + return new TypeOfField (spec, loc); } - override public Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { return DoResolve (ec, false, false); } - Expression DoResolve (EmitContext ec, bool lvalue_instance, bool out_access) + Expression DoResolve (ResolveContext ec, bool lvalue_instance, bool out_access) { - if (!FieldInfo.IsStatic){ - if (InstanceExpression == null){ - // - // This can happen when referencing an instance field using - // a fully qualified type expression: TypeName.InstanceField = xxx - // - SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); - return null; - } - + if (ResolveInstanceExpression (ec)) { // Resolve the field's instance expression while flow analysis is turned // off: when accessing a field "a.b", we must check whether the field // "a.b" is initialized, not whether the whole struct "a" is initialized. if (lvalue_instance) { - using (ec.With (EmitContext.Options.DoFlowAnalysis, false)) { + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { Expression right_side = out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; - if (InstanceExpression != EmptyExpression.Null) - InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); + InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); } } else { - ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis; - - if (InstanceExpression != EmptyExpression.Null) - InstanceExpression = InstanceExpression.Resolve (ec, rf); + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue); + } } if (InstanceExpression == null) return null; - using (ec.Set (EmitContext.Options.OmitStructFlowAnalysis)) { + using (ec.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { InstanceExpression.CheckMarshalByRefAccess (ec); } } - // TODO: the code above uses some non-standard multi-resolve rules - if (eclass != ExprClass.Invalid) - return this; + if (type.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, loc); + } - if (!ec.IsInObsoleteScope) { - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null) { - f.CheckObsoleteness (loc); - } else { - ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc); - } + if (!ec.IsObsolete) { + ObsoleteAttribute oa = spec.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (spec), loc, ec.Report); } - IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo); + var fb = spec as FixedFieldSpec; IVariableReference var = InstanceExpression as IVariableReference; + + if (lvalue_instance && var != null && var.VariableInfo != null) { + var.VariableInfo.SetFieldAssigned (ec, Name); + } if (fb != null) { IFixedExpression fe = InstanceExpression as IFixedExpression; - if (!ec.HasSet (EmitContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { - Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); + if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { + ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); } if (InstanceExpression.eclass != ExprClass.Variable) { - Report.SymbolRelatedToPreviousError (FieldInfo); - Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", - TypeManager.GetFullNameSignature (FieldInfo)); + ec.Report.SymbolRelatedToPreviousError (spec); + ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", + TypeManager.GetFullNameSignature (spec)); } else if (var != null && var.IsHoisted) { - AnonymousMethodExpression.Error_AddressOfCapturedVar (var, loc); + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc); } return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); @@ -4896,11 +4380,10 @@ namespace Mono.CSharp { return this; VariableInfo vi = var.VariableInfo; - if (!vi.IsFieldAssigned (ec, FieldInfo.Name, loc)) + if (!vi.IsFieldAssigned (ec, Name, loc)) return null; - variable_info = vi.GetSubStruct (FieldInfo.Name); - eclass = ExprClass.Variable; + variable_info = vi.GetSubStruct (Name); return this; } @@ -4927,62 +4410,62 @@ namespace Mono.CSharp { }; // The return value is always null. Returning a value simplifies calling code. - Expression Report_AssignToReadonly (Expression right_side) + Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side) { int i = 0; - if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess) + if (right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess) i += 1; if (IsStatic) i += 2; if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) i += 4; - Report.Error (codes [i], loc, msgs [i], GetSignatureForError ()); + ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ()); return null; } - override public Expression DoResolveLValue (EmitContext ec, Expression right_side) + override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) { - IVariableReference var = InstanceExpression as IVariableReference; - if (var != null && var.VariableInfo != null) - var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name); - - bool lvalue_instance = !FieldInfo.IsStatic && TypeManager.IsValueType (FieldInfo.DeclaringType); - bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess; + bool lvalue_instance = IsInstance && spec.DeclaringType.IsStruct; + bool out_access = right_side == EmptyExpression.OutAccess.Instance || right_side == EmptyExpression.LValueMemberOutAccess; Expression e = DoResolve (ec, lvalue_instance, out_access); if (e == null) return null; - FieldBase fb = TypeManager.GetField (FieldInfo); - if (fb != null) - fb.SetAssigned (); + spec.MemberDefinition.SetIsAssigned (); - if (FieldInfo.IsInitOnly) { + if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess.Instance) && + (spec.Modifiers & Modifiers.VOLATILE) != 0) { + ec.Report.Warning (420, 1, loc, + "`{0}': A volatile field references will not be treated as volatile", + spec.GetSignatureForError ()); + } + + if (spec.IsReadOnly) { // InitOnly fields can only be assigned in constructors or initializers - if (!ec.HasAny (EmitContext.Options.FieldInitializerScope | EmitContext.Options.ConstructorScope)) - return Report_AssignToReadonly (right_side); + if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope)) + return Report_AssignToReadonly (ec, right_side); - if (ec.HasSet (EmitContext.Options.ConstructorScope)) { - Type ctype = ec.CurrentType; + if (ec.HasSet (ResolveContext.Options.ConstructorScope)) { // InitOnly fields cannot be assigned-to in a different constructor from their declaring type - if (!TypeManager.IsEqual (ctype, FieldInfo.DeclaringType)) - return Report_AssignToReadonly (right_side); + if (!TypeManager.IsEqual (ec.CurrentMemberDefinition.Parent.Definition, DeclaringType.GetDefinition ())) + return Report_AssignToReadonly (ec, right_side); // static InitOnly fields cannot be assigned-to in an instance constructor if (IsStatic && !ec.IsStatic) - return Report_AssignToReadonly (right_side); + return Report_AssignToReadonly (ec, right_side); // instance constructors can't modify InitOnly fields of other instances of the same type if (!IsStatic && !(InstanceExpression is This)) - return Report_AssignToReadonly (right_side); + return Report_AssignToReadonly (ec, right_side); } } - if (right_side == EmptyExpression.OutAccess && + if (right_side == EmptyExpression.OutAccess.Instance && !IsStatic && !(InstanceExpression is This) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type)) { - Report.SymbolRelatedToPreviousError (DeclaringType); - Report.Warning (197, 1, loc, + ec.Report.SymbolRelatedToPreviousError (DeclaringType); + ec.Report.Warning (197, 1, loc, "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", GetSignatureForError ()); } @@ -4996,18 +4479,18 @@ namespace Mono.CSharp { return !IsStatic && TypeManager.IsStruct (Type) && TypeManager.mbr_type != null && TypeManager.IsSubclassOf (DeclaringType, TypeManager.mbr_type); } - public override void CheckMarshalByRefAccess (EmitContext ec) + public override void CheckMarshalByRefAccess (ResolveContext ec) { if (is_marshal_by_ref () && !(InstanceExpression is This)) { - Report.SymbolRelatedToPreviousError (DeclaringType); - 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", + ec.Report.SymbolRelatedToPreviousError (DeclaringType); + 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", GetSignatureForError ()); } } public override int GetHashCode () { - return FieldInfo.GetHashCode (); + return spec.GetHashCode (); } public bool IsFixed { @@ -5017,7 +4500,7 @@ namespace Mono.CSharp { // IVariableReference variable = InstanceExpression as IVariableReference; if (variable != null) - return TypeManager.IsStruct (InstanceExpression.Type) && variable.IsFixed; + return InstanceExpression.Type.IsStruct && variable.IsFixed; IFixedExpression fe = InstanceExpression as IFixedExpression; return fe != null && fe.IsFixed; @@ -5037,7 +4520,7 @@ namespace Mono.CSharp { if (fe == null) return false; - if (FieldInfo != fe.FieldInfo) + if (spec != fe.spec) return false; if (InstanceExpression == null || fe.InstanceExpression == null) @@ -5048,47 +4531,42 @@ namespace Mono.CSharp { public void Emit (EmitContext ec, bool leave_copy) { - ILGenerator ig = ec.ig; bool is_volatile = false; - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null){ - if ((f.ModFlags & Modifiers.VOLATILE) != 0) - is_volatile = true; + if ((spec.Modifiers & Modifiers.VOLATILE) != 0) + is_volatile = true; - f.SetMemberIsUsed (); - } + spec.MemberDefinition.SetIsUsed (); - if (FieldInfo.IsStatic){ + if (IsStatic){ if (is_volatile) - ig.Emit (OpCodes.Volatile); + ec.Emit (OpCodes.Volatile); - ig.Emit (OpCodes.Ldsfld, GetConstructedFieldInfo ()); + ec.Emit (OpCodes.Ldsfld, spec); } else { if (!prepared) EmitInstance (ec, false); // Optimization for build-in types - // TODO: Iterators don't set current container - if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.ResolveContext.CurrentType) && ec.CurrentIterator == null) { - LoadFromPtr (ig, type); + if (TypeManager.IsStruct (type) && TypeManager.IsEqual (type, ec.MemberContext.CurrentType) && TypeManager.IsEqual (InstanceExpression.Type, type)) { + ec.EmitLoadFromPtr (type); } else { - IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo); + var ff = spec as FixedFieldSpec; if (ff != null) { - ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ()); - ig.Emit (OpCodes.Ldflda, ff.Element); + ec.Emit (OpCodes.Ldflda, spec); + ec.Emit (OpCodes.Ldflda, ff.Element); } else { if (is_volatile) - ig.Emit (OpCodes.Volatile); + ec.Emit (OpCodes.Volatile); - ig.Emit (OpCodes.Ldfld, GetConstructedFieldInfo ()); + ec.Emit (OpCodes.Ldfld, spec); } } } if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); - if (!FieldInfo.IsStatic) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { temp = new LocalTemporary (this.Type); temp.Store (ec); } @@ -5097,40 +4575,28 @@ namespace Mono.CSharp { public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { - FieldAttributes fa = FieldInfo.Attributes; - bool is_static = (fa & FieldAttributes.Static) != 0; - bool is_readonly = (fa & FieldAttributes.InitOnly) != 0; - ILGenerator ig = ec.ig; - - if (is_readonly && !ec.HasSet (EmitContext.Options.ConstructorScope)){ - Report_AssignToReadonly (source); - return; - } - prepared = prepare_for_load; - EmitInstance (ec, prepared); + if (IsInstance) + EmitInstance (ec, prepared); source.Emit (ec); if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); - if (!FieldInfo.IsStatic) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { temp = new LocalTemporary (this.Type); temp.Store (ec); } } - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null){ - if ((f.ModFlags & Modifiers.VOLATILE) != 0) - ig.Emit (OpCodes.Volatile); + if ((spec.Modifiers & Modifiers.VOLATILE) != 0) + ec.Emit (OpCodes.Volatile); - f.SetAssigned (); - } + spec.MemberDefinition.SetIsAssigned (); - if (is_static) - ig.Emit (OpCodes.Stsfld, GetConstructedFieldInfo ()); + if (IsStatic) + ec.Emit (OpCodes.Stsfld, spec); else - ig.Emit (OpCodes.Stfld, GetConstructedFieldInfo ()); + ec.Emit (OpCodes.Stfld, spec); if (temp != null) { temp.Emit (ec); @@ -5146,46 +4612,35 @@ namespace Mono.CSharp { public override void EmitSideEffect (EmitContext ec) { - FieldBase f = TypeManager.GetField (FieldInfo); - bool is_volatile = f != null && (f.ModFlags & Modifiers.VOLATILE) != 0; + bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0; if (is_volatile || is_marshal_by_ref ()) base.EmitSideEffect (ec); } - public override void Error_VariableIsUsedBeforeItIsDeclared (string name) + public override void Error_VariableIsUsedBeforeItIsDeclared (Report r, string name) { - Report.Error (844, loc, + r.Error (844, loc, "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the field `{1}'", name, GetSignatureForError ()); } public void AddressOf (EmitContext ec, AddressOp mode) { - ILGenerator ig = ec.ig; - - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null){ - if ((f.ModFlags & Modifiers.VOLATILE) != 0){ - Report.Warning (420, 1, loc, "`{0}': A volatile field references will not be treated as volatile", - f.GetSignatureForError ()); - } - - if ((mode & AddressOp.Store) != 0) - f.SetAssigned (); - if ((mode & AddressOp.Load) != 0) - f.SetMemberIsUsed (); - } + if ((mode & AddressOp.Store) != 0) + spec.MemberDefinition.SetIsAssigned (); + if ((mode & AddressOp.Load) != 0) + spec.MemberDefinition.SetIsUsed (); // // Handle initonly fields specially: make a copy and then // get the address of the copy. // bool need_copy; - if (FieldInfo.IsInitOnly){ + if (spec.IsReadOnly){ need_copy = true; if (ec.HasSet (EmitContext.Options.ConstructorScope)){ - if (FieldInfo.IsStatic){ + if (IsStatic){ if (ec.IsStatic) need_copy = false; } else @@ -5197,38 +4652,31 @@ namespace Mono.CSharp { if (need_copy){ LocalBuilder local; Emit (ec); - local = ig.DeclareLocal (type); - ig.Emit (OpCodes.Stloc, local); - ig.Emit (OpCodes.Ldloca, local); + local = ec.DeclareLocal (type, false); + ec.Emit (OpCodes.Stloc, local); + ec.Emit (OpCodes.Ldloca, local); return; } - if (FieldInfo.IsStatic){ - ig.Emit (OpCodes.Ldsflda, GetConstructedFieldInfo ()); + if (IsStatic){ + ec.Emit (OpCodes.Ldsflda, spec); } else { if (!prepared) EmitInstance (ec, false); - ig.Emit (OpCodes.Ldflda, GetConstructedFieldInfo ()); + ec.Emit (OpCodes.Ldflda, spec); } } - FieldInfo GetConstructedFieldInfo () + public SLE.Expression MakeAssignExpression (BuilderContext ctx) { - if (constructed_generic_type == null) - return FieldInfo; -#if GMCS_SOURCE - return TypeBuilder.GetField (constructed_generic_type, FieldInfo); -#else - throw new NotSupportedException (); -#endif + return MakeExpression (ctx); } - - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + + public override SLE.Expression MakeExpression (BuilderContext ctx) { - FieldInfo = storey.MutateField (FieldInfo); - base.MutateHoistedGenericType (storey); - } + return SLE.Expression.Field (InstanceExpression.MakeExpression (ctx), spec.GetMetaInfo ()); + } } @@ -5239,57 +4687,64 @@ namespace Mono.CSharp { /// This is not an LValue because we need to re-write the expression, we /// can not take data from the stack and store it. /// - public class PropertyExpr : MemberExpr, IAssignMethod { - public readonly PropertyInfo PropertyInfo; - MethodInfo getter, setter; - bool is_static; + public class PropertyExpr : MemberExpr, IDynamicAssign + { + PropertySpec spec; - bool resolved; - + // getter and setter can be different for base calls + MethodSpec getter, setter; + + TypeArguments targs; LocalTemporary temp; bool prepared; - public PropertyExpr (Type container_type, PropertyInfo pi, Location l) + public PropertyExpr (PropertySpec spec, Location l) { - PropertyInfo = pi; - eclass = ExprClass.PropertyAccess; - is_static = false; + this.spec = spec; loc = l; - type = TypeManager.TypeToCoreType (pi.PropertyType); - - ResolveAccessors (container_type); + type = spec.MemberType; } + #region Properties + public override string Name { get { - return PropertyInfo.Name; + return spec.Name; } } public override bool IsInstance { get { - return !is_static; + return !IsStatic; } } public override bool IsStatic { get { - return is_static; + return spec.IsStatic; + } + } + + public PropertySpec PropertyInfo { + get { + return spec; } } - public override Expression CreateExpressionTree (EmitContext ec) + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args; if (IsSingleDimensionalArrayLength ()) { args = new Arguments (1); args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); - return CreateExpressionFactoryCall ("ArrayLength", args); + return CreateExpressionFactoryCall (ec, "ArrayLength", args); } - if (is_base) { - Error_BaseAccessInExpressionTree (loc); + if (IsBase) { + Error_BaseAccessInExpressionTree (ec, loc); return null; } @@ -5298,8 +4753,8 @@ namespace Mono.CSharp { args.Add (new Argument (new NullLiteral (loc))); else args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); - args.Add (new Argument (new TypeOfMethod (getter, loc))); - return CreateExpressionFactoryCall ("Property", args); + args.Add (new Argument (new TypeOfMethod (spec.Get, loc))); + return CreateExpressionFactoryCall (ec, "Property", args); } public Expression CreateSetterTypeOfExpression () @@ -5307,104 +4762,33 @@ namespace Mono.CSharp { return new TypeOfMethod (setter, loc); } - public override Type DeclaringType { + public override TypeSpec DeclaringType { get { - return PropertyInfo.DeclaringType; + return spec.DeclaringType; } } public override string GetSignatureForError () { - return TypeManager.GetFullNameSignature (PropertyInfo); - } - - void FindAccessors (Type invocation_type) - { - const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance | - BindingFlags.DeclaredOnly; - - Type current = PropertyInfo.DeclaringType; - for (; current != null; current = current.BaseType) { - MemberInfo[] group = TypeManager.MemberLookup ( - invocation_type, invocation_type, current, - MemberTypes.Property, flags, PropertyInfo.Name, null); - - if (group == null) - continue; - - if (group.Length != 1) - // Oooops, can this ever happen ? - return; - - PropertyInfo pi = (PropertyInfo) group [0]; - - if (getter == null) - getter = pi.GetGetMethod (true); - - if (setter == null) - setter = pi.GetSetMethod (true); - - MethodInfo accessor = getter != null ? getter : setter; - - if (!accessor.IsVirtual) - return; - } + return TypeManager.GetFullNameSignature (spec); } - // - // We also perform the permission checking here, as the PropertyInfo does not - // hold the information for the accessibility of its setter/getter - // - // TODO: Refactor to use some kind of cache together with GetPropertyFromAccessor - void ResolveAccessors (Type container_type) + public SLE.Expression MakeAssignExpression (BuilderContext ctx) { - FindAccessors (container_type); - - if (getter != null) { - MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter); - IMethodData md = TypeManager.GetMethod (the_getter); - if (md != null) - md.SetMemberIsUsed (); - - is_static = getter.IsStatic; - } - - if (setter != null) { - MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter); - IMethodData md = TypeManager.GetMethod (the_setter); - if (md != null) - md.SetMemberIsUsed (); - - is_static = setter.IsStatic; - } + return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) spec.Set.GetMetaInfo ()); } - public override void MutateHoistedGenericType (AnonymousMethodStorey storey) + public override SLE.Expression MakeExpression (BuilderContext ctx) { - if (InstanceExpression != null) - InstanceExpression.MutateHoistedGenericType (storey); - - type = storey.MutateType (type); - if (getter != null) - getter = storey.MutateGenericMethod (getter); - if (setter != null) - setter = storey.MutateGenericMethod (setter); + return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) spec.Get.GetMetaInfo ()); } - bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check) + bool InstanceResolve (ResolveContext ec, bool lvalue_instance, bool must_do_cs1540_check) { - if (is_static) { - InstanceExpression = null; + if (!ResolveInstanceExpression (ec)) return true; - } - if (InstanceExpression == null) { - SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); - return false; - } - - InstanceExpression = InstanceExpression.DoResolve (ec); + InstanceExpression = InstanceExpression.Resolve (ec); if (lvalue_instance && InstanceExpression != null) InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess); @@ -5417,137 +4801,98 @@ namespace Mono.CSharp { !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) && !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) && !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) { - Report.SymbolRelatedToPreviousError (PropertyInfo); - Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.CurrentType); + ec.Report.SymbolRelatedToPreviousError (spec); + Error_CannotAccessProtected (ec, loc, spec, InstanceExpression.Type, ec.CurrentType); return false; } return true; } - void Error_PropertyNotFound (MethodInfo mi, bool getter) + void Error_PropertyNotValid (ResolveContext ec) { - // TODO: correctly we should compare arguments but it will lead to bigger changes - if (mi is MethodBuilder) { - Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name); - return; - } - - StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType)); - sig.Append ('.'); - AParametersCollection iparams = TypeManager.GetParameterData (mi); - sig.Append (getter ? "get_" : "set_"); - sig.Append (Name); - sig.Append (iparams.GetSignatureForError ()); - - Report.SymbolRelatedToPreviousError (mi); - Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly", - Name, sig.ToString ()); + ec.Report.SymbolRelatedToPreviousError (spec); + ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language", + GetSignatureForError ()); } - public bool IsAccessibleFrom (Type invocation_type, bool lvalue) + public bool IsAccessibleFrom (TypeSpec invocation_type, bool lvalue) { bool dummy; - MethodInfo accessor = lvalue ? setter : getter; + var accessor = lvalue ? spec.Set : spec.Get; if (accessor == null && lvalue) - accessor = getter; - return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy); + accessor = spec.Get; + return accessor != null && IsMemberAccessible (invocation_type, accessor, out dummy); } bool IsSingleDimensionalArrayLength () { - if (DeclaringType != TypeManager.array_type || getter == null || Name != "Length") + if (DeclaringType != TypeManager.array_type || !spec.HasGet || Name != "Length") return false; - string t_name = InstanceExpression.Type.Name; - int t_name_len = t_name.Length; - return t_name_len > 2 && t_name [t_name_len - 2] == '['; + ArrayContainer ac = InstanceExpression.Type as ArrayContainer; + return ac != null && ac.Rank == 1; } - override public Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { - if (resolved) - return this; - - if (getter != null){ - if (TypeManager.GetParameterData (getter).Count != 0){ - Error_PropertyNotFound (getter, true); - return null; - } - } + eclass = ExprClass.PropertyAccess; - if (getter == null){ - // - // The following condition happens if the PropertyExpr was - // created, but is invalid (ie, the property is inaccessible), - // and we did not want to embed the knowledge about this in - // the caller routine. This only avoids double error reporting. - // - if (setter == null) - return null; + bool must_do_cs1540_check = false; + ec.Report.DisableReporting (); + bool res = ResolveGetter (ec, ref must_do_cs1540_check); + ec.Report.EnableReporting (); - if (InstanceExpression != EmptyExpression.Null) { - Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor", - TypeManager.GetFullNameSignature (PropertyInfo)); - return null; + if (!res) { + if (InstanceExpression != null) { + TypeSpec expr_type = InstanceExpression.Type; + ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (expr_type, Name, 0, loc); + if (ex_method_lookup != null) { + ex_method_lookup.ExtensionExpression = InstanceExpression; + ex_method_lookup.SetTypeArguments (ec, targs); + return ex_method_lookup.Resolve (ec); + } } - } - bool must_do_cs1540_check = false; - if (getter != null && - !IsAccessorAccessible (ec.CurrentType, getter, out must_do_cs1540_check)) { - PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod; - if (pm != null && pm.HasCustomAccessModifier) { - Report.SymbolRelatedToPreviousError (pm); - Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible", - TypeManager.CSharpSignature (getter)); - } - else { - Report.SymbolRelatedToPreviousError (getter); - ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter)); - } + ResolveGetter (ec, ref must_do_cs1540_check); return null; } - + if (!InstanceResolve (ec, false, must_do_cs1540_check)) return null; + if (type.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, loc); + } + + getter = CandidateToBaseOverride (spec.Get); + // // Only base will allow this invocation to happen. // if (IsBase && getter.IsAbstract) { - Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo)); - } - - if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){ - UnsafeError (loc); + Error_CannotCallAbstractBase (ec, spec.GetSignatureForError ()); } - if (!ec.IsInObsoleteScope) { - PropertyBase pb = TypeManager.GetProperty (PropertyInfo); - if (pb != null) { - pb.CheckObsoleteness (loc); - } else { - ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); - } + if (!ec.IsObsolete) { + ObsoleteAttribute oa = spec.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); } - resolved = true; - return this; } - override public Expression DoResolveLValue (EmitContext ec, Expression right_side) + override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) { - if (right_side == EmptyExpression.OutAccess) { - if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) { - Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter", - PropertyInfo.Name); + eclass = ExprClass.PropertyAccess; + + if (right_side == EmptyExpression.OutAccess.Instance) { + if (ec.CurrentBlock.Toplevel.GetParameterReference (spec.Name, loc) is MemberAccess) { + ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter", + spec.Name); } else { - Report.Error (206, loc, "A property or indexer `{0}' may not be passed as `ref' or `out' parameter", - GetSignatureForError ()); + right_side.DoResolveLValue (ec, this); } return null; } @@ -5556,69 +4901,60 @@ namespace Mono.CSharp { Error_CannotModifyIntermediateExpressionValue (ec); } - if (setter == null){ - // - // The following condition happens if the PropertyExpr was - // created, but is invalid (ie, the property is inaccessible), - // and we did not want to embed the knowledge about this in - // the caller routine. This only avoids double error reporting. - // - if (getter == null) - return null; + if (spec.IsNotRealProperty) { + Error_PropertyNotValid (ec); + return null; + } - if (ec.CurrentBlock.Toplevel.GetParameterReference (PropertyInfo.Name, loc) is MemberAccess) { - Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value", - PropertyInfo.Name); + if (!spec.HasSet){ + if (ec.CurrentBlock.Toplevel.GetParameterReference (spec.Name, loc) is MemberAccess) { + ec.Report.Error (1947, loc, "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value", + spec.Name); } else { - Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)", + ec.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)", GetSignatureForError ()); } return null; } - if (TypeManager.GetParameterData (setter).Count != 1){ - Error_PropertyNotFound (setter, false); + if (targs != null) { + base.SetTypeArguments (ec, targs); return null; } bool must_do_cs1540_check; - if (!IsAccessorAccessible (ec.CurrentType, setter, out must_do_cs1540_check)) { - PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod; - if (pm != null && pm.HasCustomAccessModifier) { - Report.SymbolRelatedToPreviousError (pm); - Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible", - TypeManager.CSharpSignature (setter)); - } - else { - Report.SymbolRelatedToPreviousError (setter); - ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter)); + if (!IsMemberAccessible (ec.CurrentType, spec.Set, out must_do_cs1540_check)) { + if (spec.HasDifferentAccessibility) { + ec.Report.SymbolRelatedToPreviousError (spec.Set); + ec.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible", + TypeManager.CSharpSignature (spec)); + } else { + ec.Report.SymbolRelatedToPreviousError (spec.Set); + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec.Set), ec.Report); } return null; } - if (!InstanceResolve (ec, TypeManager.IsStruct (PropertyInfo.DeclaringType), must_do_cs1540_check)) + if (!InstanceResolve (ec, TypeManager.IsStruct (spec.DeclaringType), must_do_cs1540_check)) return null; + + setter = CandidateToBaseOverride (spec.Set); // // Only base will allow this invocation to happen. // if (IsBase && setter.IsAbstract){ - Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo)); + Error_CannotCallAbstractBase (ec, setter.GetSignatureForError ()); } - if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe) { - UnsafeError (loc); + if (spec.MemberType.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, loc); } - if (!ec.IsInObsoleteScope) { - PropertyBase pb = TypeManager.GetProperty (PropertyInfo); - if (pb != null) { - pb.CheckObsoleteness (loc); - } else { - ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (PropertyInfo); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); - } + if (!ec.IsObsolete) { + ObsoleteAttribute oa = spec.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); } return this; @@ -5637,16 +4973,16 @@ namespace Mono.CSharp { if (IsSingleDimensionalArrayLength ()) { if (!prepared) EmitInstance (ec, false); - ec.ig.Emit (OpCodes.Ldlen); - ec.ig.Emit (OpCodes.Conv_I4); + ec.Emit (OpCodes.Ldlen); + ec.Emit (OpCodes.Conv_I4); return; } Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false); if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); - if (!is_static) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { temp = new LocalTemporary (this.Type); temp.Store (ec); } @@ -5665,8 +5001,8 @@ namespace Mono.CSharp { source.Emit (ec); if (leave_copy) { - ec.ig.Emit (OpCodes.Dup); - if (!is_static) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { temp = new LocalTemporary (this.Type); temp.Store (ec); } @@ -5688,118 +5024,137 @@ namespace Mono.CSharp { temp.Release (ec); } } + + bool ResolveGetter (ResolveContext ec, ref bool must_do_cs1540_check) + { + if (targs != null) { + base.SetTypeArguments (ec, targs); + return false; + } + + if (spec.IsNotRealProperty) { + Error_PropertyNotValid (ec); + return false; + } + + if (!spec.HasGet) { + if (InstanceExpression != EmptyExpression.Null) { + ec.Report.SymbolRelatedToPreviousError (spec); + ec.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor", + spec.GetSignatureForError ()); + return false; + } + } + + if (spec.HasGet && !IsMemberAccessible (ec.CurrentType, spec.Get, out must_do_cs1540_check)) { + if (spec.HasDifferentAccessibility) { + ec.Report.SymbolRelatedToPreviousError (spec.Get); + ec.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible", + TypeManager.CSharpSignature (spec)); + } else { + ec.Report.SymbolRelatedToPreviousError (spec.Get); + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec.Get), ec.Report); + } + + return false; + } + + return true; + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + targs = ta; + } } /// /// Fully resolved expression that evaluates to an Event /// - public class EventExpr : MemberExpr { - public readonly EventInfo EventInfo; - - bool is_static; - MethodInfo add_accessor, remove_accessor; + public class EventExpr : MemberExpr + { + readonly EventSpec spec; - public EventExpr (EventInfo ei, Location loc) + public EventExpr (EventSpec spec, Location loc) { - EventInfo = ei; + this.spec = spec; this.loc = loc; - eclass = ExprClass.EventAccess; - - add_accessor = TypeManager.GetAddMethod (ei); - remove_accessor = TypeManager.GetRemoveMethod (ei); - if (add_accessor.IsStatic || remove_accessor.IsStatic) - is_static = true; - - if (EventInfo is MyEventBuilder){ - MyEventBuilder eb = (MyEventBuilder) EventInfo; - type = eb.EventType; - eb.SetUsed (); - } else - type = EventInfo.EventHandlerType; } public override string Name { get { - return EventInfo.Name; + return spec.Name; } } public override bool IsInstance { get { - return !is_static; + return !spec.IsStatic; } } public override bool IsStatic { get { - return is_static; + return spec.IsStatic; } } - public override Type DeclaringType { + public override TypeSpec DeclaringType { get { - return EventInfo.DeclaringType; + return spec.DeclaringType; } } - public void Error_AssignmentEventOnly () + public void Error_AssignmentEventOnly (ResolveContext ec) { - Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator", + ec.Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator", GetSignatureForError ()); } - public override MemberExpr ResolveMemberAccess (EmitContext ec, Expression left, Location loc, - SimpleName original) + public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) { // // If the event is local to this class, we transform ourselves into a FieldExpr // - if (EventInfo.DeclaringType == ec.CurrentType || - TypeManager.IsNestedChildOf(ec.CurrentType, EventInfo.DeclaringType)) { - EventField mi = TypeManager.GetEventField (EventInfo); + if (spec.DeclaringType == ec.CurrentType || + TypeManager.IsNestedChildOf(ec.CurrentType, spec.DeclaringType)) { + + // TODO: Breaks dynamic binder as currect context fields are imported and not compiled + EventField mi = spec.MemberDefinition as EventField; - if (mi != null) { - if (!ec.IsInObsoleteScope) + if (mi != null && mi.HasBackingField) { + mi.SetIsUsed (); + if (!ec.IsObsolete) mi.CheckObsoleteness (loc); - if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (EmitContext.Options.CompoundAssignmentScope)) - Error_AssignmentEventOnly (); + if ((mi.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0 && !ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) + Error_AssignmentEventOnly (ec); - FieldExpr ml = new FieldExpr (mi.BackingField.FieldBuilder, loc); + FieldExpr ml = new FieldExpr (mi.BackingField, loc); InstanceExpression = null; - return ml.ResolveMemberAccess (ec, left, loc, original); + return ml.ResolveMemberAccess (ec, left, original); } } - if (left is This && !ec.HasSet (EmitContext.Options.CompoundAssignmentScope)) - Error_AssignmentEventOnly (); + if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) + Error_AssignmentEventOnly (ec); - return base.ResolveMemberAccess (ec, left, loc, original); + return base.ResolveMemberAccess (ec, left, original); } - bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check) + bool InstanceResolve (ResolveContext ec, bool must_do_cs1540_check) { - if (is_static) { - InstanceExpression = null; - return true; - } - - if (InstanceExpression == null) { - SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); - return false; + if (IsBase && spec.IsAbstract) { + Error_CannotCallAbstractBase (ec, spec.GetSignatureForError ()); } - InstanceExpression = InstanceExpression.DoResolve (ec); - if (InstanceExpression == null) - return false; + if (!ResolveInstanceExpression (ec)) + return true; - if (IsBase && add_accessor.IsAbstract) { - Error_CannotCallAbstractBase(TypeManager.CSharpSignature(add_accessor)); - return false; - } + InstanceExpression.Resolve (ec); // // This is using the same mechanism as the CS1540 check in PropertyExpr. @@ -5811,87 +5166,91 @@ namespace Mono.CSharp { !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.CurrentType) && !TypeManager.IsNestedChildOf (ec.CurrentType, InstanceExpression.Type) && !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.CurrentType)) { - Report.SymbolRelatedToPreviousError (EventInfo); - ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); + ec.Report.SymbolRelatedToPreviousError (spec); + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report); return false; } return true; } - public bool IsAccessibleFrom (Type invocation_type) + public bool IsAccessibleFrom (TypeSpec invocation_type) { bool dummy; - return IsAccessorAccessible (invocation_type, add_accessor, out dummy) && - IsAccessorAccessible (invocation_type, remove_accessor, out dummy); + return IsMemberAccessible (invocation_type, spec.AccessorAdd, out dummy) && + IsMemberAccessible (invocation_type, spec.AccessorRemove, out dummy); } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); } - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) { // contexts where an LValue is valid have already devolved to FieldExprs - Error_CannotAssign (); + Error_CannotAssign (ec); return null; } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { + eclass = ExprClass.EventAccess; + bool must_do_cs1540_check; - if (!(IsAccessorAccessible (ec.CurrentType, add_accessor, out must_do_cs1540_check) && - IsAccessorAccessible (ec.CurrentType, remove_accessor, out must_do_cs1540_check))) { - Report.SymbolRelatedToPreviousError (EventInfo); - ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); + if (!(IsMemberAccessible (ec.CurrentType, spec.AccessorAdd, out must_do_cs1540_check) && + IsMemberAccessible (ec.CurrentType, spec.AccessorRemove, out must_do_cs1540_check))) { + ec.Report.SymbolRelatedToPreviousError (spec); + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (spec), ec.Report); return null; } + type = spec.MemberType; + if (!InstanceResolve (ec, must_do_cs1540_check)) return null; - if (!ec.HasSet (EmitContext.Options.CompoundAssignmentScope)) { - Error_CannotAssign (); + if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { + Error_CannotAssign (ec); return null; } - if (!ec.IsInObsoleteScope) { - EventField ev = TypeManager.GetEventField (EventInfo); - if (ev != null) { - ev.CheckObsoleteness (loc); - } else { - ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (EventInfo); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc); - } + if (!ec.IsObsolete) { + var oa = spec.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); } + + spec.MemberDefinition.SetIsUsed (); return this; } public override void Emit (EmitContext ec) { - Error_CannotAssign (); + throw new NotSupportedException (); + //Error_CannotAssign (); } - public void Error_CannotAssign () + public void Error_CannotAssign (ResolveContext ec) { - Report.Error (70, loc, + ec.Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'", - GetSignatureForError (), TypeManager.CSharpName (EventInfo.DeclaringType)); + GetSignatureForError (), TypeManager.CSharpName (spec.DeclaringType)); } public override string GetSignatureForError () { - return TypeManager.CSharpSignature (EventInfo); + return TypeManager.CSharpSignature (spec); } public void EmitAddOrRemove (EmitContext ec, bool is_add, Expression source) { Arguments args = new Arguments (1); args.Add (new Argument (source)); - Invocation.EmitCall (ec, IsBase, InstanceExpression, is_add ? add_accessor : remove_accessor, args, loc); + Invocation.EmitCall (ec, IsBase, InstanceExpression, + is_add ? spec.AccessorAdd : spec.AccessorRemove, + args, loc); } } @@ -5899,22 +5258,20 @@ namespace Mono.CSharp { { LocalInfo li; - public TemporaryVariable (Type type, Location loc) + public TemporaryVariable (TypeSpec type, Location loc) { this.type = type; this.loc = loc; - eclass = ExprClass.Variable; } - public override Expression CreateExpressionTree (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); } - public override Expression DoResolve (EmitContext ec) + protected override Expression DoResolve (ResolveContext ec) { - if (li != null) - return this; + eclass = ExprClass.Variable; TypeExpr te = new TypeExpression (type, loc); li = ec.CurrentBlock.AddTemporaryVariable (te, loc); @@ -5933,9 +5290,9 @@ namespace Mono.CSharp { return this; } - public override Expression DoResolveLValue (EmitContext ec, Expression right_side) + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) { - return DoResolve (ec); + return Resolve (ec); } public override void Emit (EmitContext ec) @@ -5948,9 +5305,9 @@ namespace Mono.CSharp { EmitAssign (ec, source, false, false); } - public override HoistedVariable GetHoistedVariable (EmitContext ec) + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) { - return li.HoistedVariableReference; + return li.HoistedVariant; } public override bool IsFixed { @@ -5986,27 +5343,28 @@ namespace Mono.CSharp { class VarExpr : SimpleName { // Used for error reporting only - ArrayList initializer; + int initializers_count; public VarExpr (Location loc) : base ("var", loc) { + initializers_count = 1; } - public ArrayList VariableInitializer { + public int VariableInitializersCount { set { - this.initializer = value; + this.initializers_count = value; } } - public bool InferType (EmitContext ec, Expression right_side) + public bool InferType (ResolveContext ec, Expression right_side) { if (type != null) throw new InternalErrorException ("An implicitly typed local variable could not be redefined"); type = right_side.Type; - if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod) { - Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'", + if (type == TypeManager.null_type || type == TypeManager.void_type || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) { + ec.Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'", right_side.GetSignatureForError ()); return false; } @@ -6015,36 +5373,35 @@ namespace Mono.CSharp { return true; } - protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec) + protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec) { if (RootContext.Version < LanguageVersion.V_3) base.Error_TypeOrNamespaceNotFound (ec); else - Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration"); + ec.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration"); } - public override TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent) + public override TypeExpr ResolveAsContextualType (IMemberContext rc, bool silent) { TypeExpr te = base.ResolveAsContextualType (rc, true); if (te != null) return te; if (RootContext.Version < LanguageVersion.V_3) - Report.FeatureIsNotAvailable (loc, "implicitly typed local variable"); + rc.Compiler.Report.FeatureIsNotAvailable (loc, "implicitly typed local variable"); - if (initializer == null) + if (initializers_count == 1) return null; - if (initializer.Count > 1) { - Location loc_init = ((CSharpParser.VariableDeclaration) initializer[1]).Location; - Report.Error (819, loc_init, "An implicitly typed local variable declaration cannot include multiple declarators"); - initializer = null; + if (initializers_count > 1) { + rc.Compiler.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators"); + initializers_count = 1; return null; } - Expression variable_initializer = ((CSharpParser.VariableDeclaration) initializer[0]).expression_or_array_initializer; - if (variable_initializer == null) { - Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer"); + if (initializers_count == 0) { + initializers_count = 1; + rc.Compiler.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer"); return null; }