X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=fbb5438040925c729862e2569ce71f4c88c8c59e;hb=b7461c8e10acd19aa25d0ff7946719b19fad0157;hp=b0100b958342d8636a229b2bf7bc6aaec3cd94bf;hpb=55754229608544e1dfebc13d741292125a1ab6a9;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index b0100b95834..fbb54380409 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -228,6 +228,15 @@ namespace Mono.CSharp { return null; } + // + // 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) + { + return ResolveAsTypeTerminal (rc, silent); + } + // // This is used to resolve the expression as a type, a null // value will be returned if the expression is not a type @@ -239,7 +248,7 @@ namespace Mono.CSharp { if (te == null) return null; - if (!silent) { + 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); @@ -326,6 +335,10 @@ namespace Mono.CSharp { public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl) { + // The error was already reported as CS1660 + if (type == TypeManager.anonymous_method_type) + return; + if (Type.FullName == target.FullName){ Report.ExtraInformation (loc, String.Format ( @@ -336,7 +349,7 @@ namespace Mono.CSharp { if (expl) { Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'", - GetSignatureForError (), TypeManager.CSharpName (target)); + TypeManager.CSharpName (type), TypeManager.CSharpName (target)); return; } @@ -360,14 +373,25 @@ namespace Mono.CSharp { return; } - Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'", - Type == TypeManager.anonymous_method_type ? - "anonymous method" : "`" + GetSignatureForError () + "'", + Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", + TypeManager.CSharpName (type), TypeManager.CSharpName (target)); } + protected void Error_VariableIsUsedBeforeItIsDeclared (string name) + { + Report.Error (841, loc, "The variable `{0}' cannot be used before it is declared", + name); + } + + protected virtual void Error_TypeDoesNotContainDefinition (Type type, string name) + { + Error_TypeDoesNotContainDefinition (loc, type, name); + } + public static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name) { + Report.SymbolRelatedToPreviousError (type); Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'", TypeManager.CSharpName (type), name); } @@ -396,8 +420,7 @@ namespace Mono.CSharp { return ResolveFlags.VariableOrValue; default: - throw new Exception ("Expression " + GetType () + - " ExprClass is Invalid after resolve"); + throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve"); } } } @@ -678,11 +701,11 @@ namespace Mono.CSharp { } } - return new MethodGroupExpr (methods, loc); + return new MethodGroupExpr (methods, queried_type, loc); } if (mi [0] is MethodBase) - return new MethodGroupExpr (mi, loc); + return new MethodGroupExpr (mi, queried_type, loc); return ExprClassFromMemberInfo (container_type, mi [0], loc); } @@ -727,14 +750,7 @@ namespace Mono.CSharp { /// look for private members and display a useful debugging message if we /// find it. /// - public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, - Type queried_type, string name, Location loc) - { - return MemberLookupFinal (ec, qualifier_type, queried_type, name, - AllMemberTypes, AllBindingFlags, loc); - } - - public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, + protected Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) @@ -745,17 +761,17 @@ namespace Mono.CSharp { e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc); - if (e == null && errors == Report.Errors) - // No errors were reported by MemberLookup, but there was an error. - MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc); + if (e != null || errors != Report.Errors) + return e; - return e; + // No errors were reported by MemberLookup, but there was an error. + return Error_MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, + name, null, mt, bf); } - public static void MemberLookupFailed (Type container_type, Type qualifier_type, - Type queried_type, string name, - string class_name, bool complain_if_none_found, - Location loc) + protected virtual Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type, + Type queried_type, string name, string class_name, + MemberTypes mt, BindingFlags bf) { if (almostMatchedMembers.Count != 0) { for (int i = 0; i < almostMatchedMembers.Count; ++i) { @@ -790,7 +806,7 @@ namespace Mono.CSharp { } } almostMatchedMembers.Clear (); - return; + return null; } MemberInfo[] lookup = null; @@ -798,20 +814,28 @@ namespace Mono.CSharp { class_name = "global::"; } else { lookup = TypeManager.MemberLookup (queried_type, null, queried_type, - AllMemberTypes, AllBindingFlags | - BindingFlags.NonPublic, name, null); + mt, (bf & ~BindingFlags.Public) | BindingFlags.NonPublic, + name, null); + + if (lookup != null) { + Report.SymbolRelatedToPreviousError (lookup [0]); + ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0])); + return Error_MemberLookupFailed (lookup); + } + + lookup = TypeManager.MemberLookup (queried_type, null, queried_type, + AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic, + name, null); } if (lookup == null) { - if (!complain_if_none_found) - return; - - if (class_name != null) - Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'", - name, class_name); - else - Error_TypeDoesNotContainDefinition (loc, queried_type, name); - return; + if (class_name != null) { + Report.Error (103, loc, "The name `{0}' does not exist in the current context", + name); + } else { + Error_TypeDoesNotContainDefinition (queried_type, name); + } + return null; } if (TypeManager.MemberLookup (queried_type, null, queried_type, @@ -825,20 +849,22 @@ namespace Mono.CSharp { "requires {1} type arguments", TypeManager.CSharpName (t), TypeManager.GetNumberOfTypeArguments (t).ToString ()); - return; + return null; } } - MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor, - BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null); - if (name == ".ctor" && ml.Count == 0) - { - Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type)); - return; + return Error_MemberLookupFailed (lookup); + } + + protected virtual Expression Error_MemberLookupFailed (MemberInfo[] members) + { + for (int i = 0; i < members.Length; ++i) { + if (!(members [i] is MethodBase)) + return null; } - Report.SymbolRelatedToPreviousError (lookup [0]); - ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0])); + // By default propagate the closest candidates upwards + return new MethodGroupExpr (members, type, loc); } /// @@ -861,27 +887,26 @@ namespace Mono.CSharp { static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc) { - MethodBase method; - Expression operator_group; + MethodGroupExpr operator_group; #if GMCS_SOURCE if (TypeManager.IsNullableType (e.Type)) return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec); #endif - operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc); + operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr; if (operator_group == null) return null; - ArrayList arguments = new ArrayList (); + ArrayList arguments = new ArrayList (1); arguments.Add (new Argument (e, Argument.AType.Expression)); - method = ((MethodGroupExpr) operator_group).OverloadResolve ( + operator_group = operator_group.OverloadResolve ( ec, arguments, false, loc); - if (method == null) + if (operator_group == null) return null; - return new StaticCallExpr ((MethodInfo) method, arguments, loc); + return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc); } /// @@ -1231,16 +1256,26 @@ namespace Mono.CSharp { /// would be "unsigned int". /// /// - public class EmptyCast : Expression { + public class EmptyCast : Expression + { protected Expression child; - public EmptyCast (Expression child, Type return_type) + protected EmptyCast (Expression child, Type return_type) { eclass = child.eclass; loc = child.Location; type = return_type; this.child = child; } + + public static Expression Create (Expression child, Type type) + { + Constant c = child as Constant; + if (c != null) + return new EmptyConstantCast (c, type); + + return new EmptyCast (child, type); + } public override Expression DoResolve (EmitContext ec) { @@ -1463,6 +1498,10 @@ namespace Mono.CSharp { get { return child.IsNegative; } } + public override bool IsZeroInteger { + get { return child.IsZeroInteger; } + } + public override void Emit (EmitContext ec) { child.Emit (ec); @@ -1567,12 +1606,16 @@ namespace Mono.CSharp { public override Constant ConvertImplicitly (Type type) { - if (Type == 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; - if (type.UnderlyingSystemType != Child.Type) + Type child_type = TypeManager.DropGenericTypeArguments (Child.Type); + if (type.UnderlyingSystemType != child_type) Child = Child.ConvertImplicitly (type.UnderlyingSystemType); return this; } @@ -1950,7 +1993,7 @@ namespace Mono.CSharp { /// of a dotted-name. /// public class SimpleName : Expression { - public string Name; + public readonly string Name; public readonly TypeArguments Arguments; bool in_transit; @@ -2012,7 +2055,7 @@ namespace Mono.CSharp { public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) { - if (ec.IsFieldInitializer) + if (ec.IsInFieldInitializer) Report.Error (236, l, "A field initializer cannot reference the nonstatic field, method, or property `{0}'", name); @@ -2063,7 +2106,7 @@ namespace Mono.CSharp { FullNamedExpression ResolveNested (IResolveContext ec, Type t) { - if (!TypeManager.IsGenericTypeDefinition (t)) + if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t)) return null; DeclSpace ds = ec.DeclContainer; @@ -2125,10 +2168,16 @@ namespace Mono.CSharp { if (silent || errors != Report.Errors) return null; + Error_TypeOrNamespaceNotFound (ec); + return null; + } + + protected virtual void Error_TypeOrNamespaceNotFound (IResolveContext ec) + { MemberCore mc = ec.DeclContainer.GetDefinition (Name); if (mc != null) { Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc); - return null; + return; } string ns = ec.DeclContainer.NamespaceEntry.NS.Name; @@ -2137,19 +2186,26 @@ namespace Mono.CSharp { Type type = a.GetType (fullname); if (type != null) { Report.SymbolRelatedToPreviousError (type); - Expression.ErrorIsInaccesible (loc, fullname); - return null; + Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type)); + return; } } Type t = ec.DeclContainer.LookupAnyGeneric (Name); if (t != null) { Namespace.Error_InvalidNumberOfTypeArguments (t, loc); - return null; + return; } + if (Arguments != null) { + FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true); + if (retval != null) { + Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc, "type"); + return; + } + } + NamespaceEntry.Error_NamespaceNotFound (loc, Name); - return null; } // TODO: I am still not convinced about this. If someone else will need it @@ -2176,9 +2232,11 @@ namespace Mono.CSharp { { if (in_transit) return null; - in_transit = true; + in_transit = true; Expression e = DoSimpleNameResolve (ec, right_side, intermediate); + in_transit = false; + if (e == null) return null; @@ -2248,33 +2306,47 @@ namespace Mono.CSharp { else return pref.Resolve (ec); } + + Expression expr = current_block.Toplevel.GetTransparentIdentifier (Name); + if (expr != null) { + if (right_side != null) + return expr.ResolveLValue (ec, right_side, loc); + return expr.Resolve (ec); + } } // // Stage 2: Lookup members // - DeclSpace lookup_ds = ec.DeclContainer; Type almost_matched_type = null; ArrayList almost_matched = null; - do { + for (DeclSpace lookup_ds = ec.DeclContainer; lookup_ds != null; lookup_ds = lookup_ds.Parent) { + // either RootDeclSpace or GenericMethod if (lookup_ds.TypeBuilder == null) - break; + continue; e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc); - if (e != null) - break; + if (e != null) { + if (e is PropertyExpr) { + // 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 (((PropertyExpr) e).IsAccessibleFrom (ec.ContainerType, right_side != null)) + break; + } else if (e is EventExpr) { + if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType)) + break; + } else { + break; + } + e = null; + } if (almost_matched == null && almostMatchedMembers.Count > 0) { almost_matched_type = lookup_ds.TypeBuilder; almost_matched = (ArrayList) almostMatchedMembers.Clone (); } - - lookup_ds =lookup_ds.Parent; - } while (lookup_ds != null); - - if (e == null && ec.ContainerType != null) - e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc); + } if (e == null) { if (almost_matched == null && almostMatchedMembers.Count > 0) { @@ -2285,11 +2357,25 @@ namespace Mono.CSharp { } if (e == null) { + if (current_block != null) { + IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name); + if (ikv != null) { + LocalInfo li = ikv as LocalInfo; + // Supress CS0219 warning + if (li != null) + li.Used = true; + + Error_VariableIsUsedBeforeItIsDeclared (Name); + return null; + } + } + if (almost_matched != null) almostMatchedMembers = almost_matched; if (almost_matched_type == null) almost_matched_type = ec.ContainerType; - MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc); + Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name, + ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags); return null; } @@ -2307,7 +2393,7 @@ namespace Mono.CSharp { Expression left; if (me.IsInstance) { - if (ec.IsStatic || ec.IsFieldInitializer) { + if (ec.IsStatic || ec.IsInFieldInitializer) { // // Note that an MemberExpr can be both IsInstance and IsStatic. // An unresolved MethodGroupExpr can contain both kinds of methods @@ -2368,14 +2454,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - // - // If this is ever reached, then we failed to - // find the name as a namespace - // - - Error (103, "The name `" + Name + - "' does not exist in the class `" + - ec.DeclContainer.Name + "'"); + throw new InternalErrorException ("The resolve phase was not executed"); } public override string ToString () @@ -2385,6 +2464,11 @@ namespace Mono.CSharp { public override string GetSignatureForError () { + if (Arguments != null) { + return TypeManager.RemoveGenericArity (Name) + "<" + + Arguments.GetSignatureForError () + ">"; + } + return Name; } @@ -2550,61 +2634,111 @@ namespace Mono.CSharp { return this; } - static readonly char [] dot_array = { '.' }; - protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + private class UnexpectedType { - // If name is of the form `N.I', first lookup `N', then search a member `I' in it. - string rest = null; - string lookup_name = name; - int pos = name.IndexOf ('.'); - if (pos >= 0) { - rest = name.Substring (pos + 1); - lookup_name = name.Substring (0, pos); - } - - FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null); - - if (resolved != null && rest != null) { - // Now handle the rest of the the name. - string [] elements = rest.Split (dot_array); - string element; - int count = elements.Length; - int i = 0; - while (i < count && resolved != null && resolved is Namespace) { - Namespace ns = resolved as Namespace; - element = elements [i++]; - lookup_name += "." + element; - resolved = ns.Lookup (ec.DeclContainer, element, Location.Null); - } + } - if (resolved != null && resolved is TypeExpr) { - Type t = ((TypeExpr) resolved).Type; - while (t != null) { - if (!ec.DeclContainer.CheckAccessLevel (t)) { - resolved = null; - lookup_name = t.FullName; - break; - } - if (i == count) { - type = t; - return this; - } - t = TypeManager.GetNestedType (t, elements [i++]); + // This performes recursive type lookup, providing support for generic types. + // For example, given the type: + // + // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]] + // + // The types will be checked in the following order: + // _ + // System | + // System.Collections | + // System.Collections.Generic | + // _ | + // System | recursive call 1 | + // System.Int32 _| | main method call + // _ | + // System | recursive call 2 | + // System.String _| | + // | + // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]] _| + // + private Type TypeLookup (IResolveContext ec, string name) + { + int index = 0; + int dot = 0; + bool done = false; + FullNamedExpression resolved = null; + Type type = null; + Type recursive_type = null; + while (index < name.Length) { + if (name[index] == '[') { + int open = index; + int braces = 1; + do { + index++; + if (name[index] == '[') + braces++; + else if (name[index] == ']') + braces--; + } while (braces > 0); + recursive_type = TypeLookup (ec, name.Substring (open + 1, index - open - 1)); + if (recursive_type == null || (recursive_type == typeof(UnexpectedType))) + return recursive_type; + } + else { + if (name[index] == ',') + done = true; + else if ((name[index] == '.' && !done) || (index == name.Length && name[0] != '[')) { + string substring = name.Substring(dot, index - dot); + + if (resolved == null) + resolved = RootNamespace.Global.Lookup (ec.DeclContainer, substring, Location.Null); + else if (resolved is Namespace) + resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null); + else if (type != null) + type = TypeManager.GetNestedType (type, substring); + else + return null; + + if (resolved == null) + return null; + else if (type == null && resolved is TypeExpr) + type = resolved.Type; + + dot = index + 1; } } + index++; } + if (name[0] != '[') { + string substring = name.Substring(dot, index - dot); - if (resolved == null) { - NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name); - return null; + if (type != null) + return TypeManager.GetNestedType (type, substring); + + if (resolved != null) { + resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null); + if (resolved is TypeExpr) + return resolved.Type; + + if (resolved == null) + return null; + + resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc); + return typeof (UnexpectedType); + } + else + return null; + } + else + return recursive_type; } - if (!(resolved is TypeExpr)) { - resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc); + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + { + Type t = TypeLookup (ec, name); + if (t == null) { + NamespaceEntry.Error_NamespaceNotFound (loc, name); return null; } - - type = resolved.Type; + if (t == typeof(UnexpectedType)) + return null; + type = t; return this; } @@ -2620,6 +2754,14 @@ namespace Mono.CSharp { { // CloneTo: Nothing, we do not keep any state on this expression } + + public override string GetSignatureForError () + { + if (type == null) + return TypeManager.CSharpName (name); + + return base.GetSignatureForError (); + } } /// @@ -2805,6 +2947,10 @@ namespace Mono.CSharp { // if (left is TypeExpr) { + left = left.ResolveAsTypeTerminal (ec, true); + if (left == null) + return null; + if (!IsStatic) { SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; @@ -2858,16 +3004,14 @@ namespace Mono.CSharp { /// public class ExtensionMethodGroupExpr : MethodGroupExpr { - NamespaceEntry namespaceEntry; - readonly bool usingCandidates; + readonly NamespaceEntry namespaceEntry; + public Expression ExtensionExpression; + Argument extension_argument; - public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, bool usingCandidates, - Type extensionType, Location l) - : base (list, l) + public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l) + : base (list, extensionType, l) { this.namespaceEntry = n; - this.usingCandidates = usingCandidates; - this.type = extensionType; } public override bool IsBase { @@ -2882,61 +3026,91 @@ namespace Mono.CSharp { get { return namespaceEntry == null; } } - public override MethodBase OverloadExtensionResolve (EmitContext ec, ref ArrayList arguments, ref MethodGroupExpr mg, - Expression expr, Location loc) + public override void EmitArguments (EmitContext ec, ArrayList arguments) + { + if (arguments == null) + arguments = new ArrayList (1); + arguments.Insert (0, extension_argument); + base.EmitArguments (ec, arguments); + } + + public override void EmitCall (EmitContext ec, ArrayList arguments) { if (arguments == null) arguments = new ArrayList (1); - - Argument a = new Argument (((MemberAccess)expr).Expr); - a.Resolve (ec, loc); - arguments.Insert (0, a); + arguments.Insert (0, extension_argument); + base.EmitCall (ec, arguments); + } - mg = this; - do { - MethodBase method = mg.OverloadResolve (ec, arguments, true, loc); - if (method != null) - return method; + public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc) + { + if ((ExtensionExpression.eclass & (ExprClass.Value | ExprClass.Variable)) == 0) + return base.OverloadResolve (ec, arguments, may_fail, loc); - ExtensionMethodGroupExpr e = namespaceEntry.LookupExtensionMethod (type, usingCandidates, Name); - if (e == null) - return mg.OverloadResolve (ec, arguments, false, loc); + if (arguments == null) + arguments = new ArrayList (1); + + arguments.Insert (0, new Argument (ExtensionExpression)); + MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespaceEntry, loc); - mg = e; - namespaceEntry = e.namespaceEntry; - } while (true); + // Store resolved argument and restore original arguments + if (mg != null) + ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0]; + arguments.RemoveAt (0); + + return mg; } + + MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc) + { + // Use normal resolve rules + MethodGroupExpr mg = base.OverloadResolve (ec, arguments, ns != null, loc); + if (mg != null) + return mg; + + if (ns == null) + return null; + + // Search continues + ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name); + if (e == null) + return base.OverloadResolve (ec, arguments, false, loc); + + e.ExtensionExpression = ExtensionExpression; + return e.ResolveOverloadExtensions (ec, arguments, e.namespaceEntry, loc); + } } /// - /// MethodGroup Expression. - /// - /// This is a fully resolved expression that evaluates to a type + /// MethodGroupExpr represents a group of method candidates which + /// can be resolved to the best method overload /// - public class MethodGroupExpr : MemberExpr { + public class MethodGroupExpr : MemberExpr + { + public interface IErrorHandler + { + bool NoExactMatch (EmitContext ec, MethodBase method); + } + + public static IErrorHandler CustomErrorHandler; public MethodBase [] Methods; - bool has_type_arguments = false; - bool identical_type_name = false; + MethodBase best_candidate; + bool has_type_arguments; + bool identical_type_name; bool is_base; - public MethodGroupExpr (MemberInfo [] mi, Location l) + public MethodGroupExpr (MemberInfo [] mi, Type type, Location l) + : this (type, l) { Methods = new MethodBase [mi.Length]; mi.CopyTo (Methods, 0); - eclass = ExprClass.MethodGroup; - - // Set the type to something that will never be useful, which will - // trigger the proper conversions. - type = typeof (MethodGroupExpr); - loc = l; } - public MethodGroupExpr (ArrayList list, Location l) + public MethodGroupExpr (ArrayList list, Type type, Location l) + : this (type, l) { - Methods = new MethodBase [list.Count]; - try { - list.CopyTo (Methods, 0); + Methods = (MethodBase[])list.ToArray (typeof (MethodBase)); } catch { foreach (MemberInfo m in list){ if (!(m is MethodBase)){ @@ -2947,9 +3121,14 @@ namespace Mono.CSharp { throw; } - loc = l; + + } + + protected MethodGroupExpr (Type type, Location loc) + { + this.loc = loc; eclass = ExprClass.MethodGroup; - type = TypeManager.object_type; + this.type = type; } public override Type DeclaringType { @@ -2966,10 +3145,6 @@ namespace Mono.CSharp { get { return has_type_arguments; } - - set { - has_type_arguments = value; - } } public bool IdenticalTypeName { @@ -2993,6 +3168,9 @@ namespace Mono.CSharp { public override string GetSignatureForError () { + if (best_candidate != null) + return TypeManager.CSharpSignature (best_candidate); + return TypeManager.CSharpSignature (Methods [0]); } @@ -3021,6 +3199,16 @@ namespace Mono.CSharp { return false; } } + + public static explicit operator ConstructorInfo (MethodGroupExpr mg) + { + return (ConstructorInfo)mg.best_candidate; + } + + public static explicit operator MethodInfo (MethodGroupExpr mg) + { + return (MethodInfo)mg.best_candidate; + } /// /// Determines "better conversion" as specified in 14.4.2.3 @@ -3263,9 +3451,6 @@ namespace Mono.CSharp { override public Expression DoResolve (EmitContext ec) { - if (!IsInstance) - InstanceExpression = null; - if (InstanceExpression != null) { InstanceExpression = InstanceExpression.DoResolve (ec); if (InstanceExpression == null) @@ -3285,13 +3470,143 @@ namespace Mono.CSharp { { ReportUsageError (); } + + public virtual void EmitArguments (EmitContext ec, ArrayList arguments) + { + Invocation.EmitArguments (ec, best_candidate, arguments, false, null); + } + + public virtual void EmitCall (EmitContext ec, ArrayList arguments) + { + Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc); + } + + protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method, + Type delegate_type, Argument a, ParameterData expected_par) + { + if (a is CollectionElementInitializer.ElementInitializerArgument) { + Report.SymbolRelatedToPreviousError (method); + if ((expected_par.ParameterModifier (idx) & Parameter.Modifier.ISBYREF) != 0) { + 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", + TypeManager.CSharpSignature (method)); + } else if (delegate_type == null) { + Report.SymbolRelatedToPreviousError (method); + Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", + TypeManager.CSharpSignature (method)); + } else + Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", + TypeManager.CSharpName (delegate_type)); + + Parameter.Modifier mod = expected_par.ParameterModifier (idx); + + string index = (idx + 1).ToString (); + if ((mod & Parameter.Modifier.ISBYREF) != (a.Modifier & Parameter.Modifier.ISBYREF) || + (mod & Parameter.Modifier.ISBYREF) != 0) { + if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0) + Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword", + index, Parameter.GetModifierSignature (a.Modifier)); + else + Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword", + index, Parameter.GetModifierSignature (mod)); + } else { + string p1 = Argument.FullDesc (a); + string p2 = TypeManager.CSharpName (expected_par.ParameterType (idx)); + + if (p1 == p2) { + Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous "); + Report.SymbolRelatedToPreviousError (a.Expr.Type); + Report.SymbolRelatedToPreviousError (expected_par.ParameterType (idx)); + } + Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2); + } + } + + protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters) + { + return parameters.Count; + } public static bool IsAncestralType (Type first_type, Type second_type) { return first_type != second_type && (TypeManager.IsSubclassOf (second_type, first_type) || TypeManager.ImplementsInterface (second_type, first_type)); - } + } + + /// + /// Determines if the candidate method is applicable (section 14.4.2.1) + /// to the given set of arguments + /// A return value rates candidate method compatibility, + /// 0 = the best, int.MaxValue = the worst + /// + public int IsApplicable (EmitContext ec, + ArrayList arguments, int arg_count, ref MethodBase method) + { + MethodBase candidate = method; + + ParameterData pd = TypeManager.GetParameterData (candidate); + int param_count = GetApplicableParametersCount (candidate, pd); + + if (arg_count != param_count) + return int.MaxValue; + + // + // 1. Infer type arguments for generic method + // +#if GMCS_SOURCE + if (!HasTypeArguments && TypeManager.IsGenericMethod (method)) { + int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate); + if (score != 0) + return --score; + + if (TypeManager.IsGenericMethodDefinition (candidate)) + throw new InternalErrorException ("a generic method definition took part in overload resolution"); + + pd = TypeManager.GetParameterData (candidate); + } +#endif + + // + // 2. Each argument has to be implicitly converible to method parameter + // + for (int i = arg_count; i > 0; ) { + i--; + + Argument a = (Argument) arguments [i]; + + Parameter.Modifier a_mod = a.Modifier & + ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + + Parameter.Modifier p_mod = pd.ParameterModifier (i) & + ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS); + + Type pt = pd.ParameterType (i); + + // FIXME: Kill this abomination (EmitContext.TempEc) + EmitContext prevec = EmitContext.TempEc; + EmitContext.TempEc = ec; + try { + if (pt.IsByRef) + pt = pt.GetElementType (); + + if (!Convert.ImplicitConversionExists (ec, a.Expr, pt)) + return ++i * 2; + + if (a_mod != p_mod) + return ++i * 2 - 1; + + } finally { + EmitContext.TempEc = prevec; + } + } + + method = candidate; + return 0; + } public static bool IsOverride (MethodBase cand_method, MethodBase base_method) { @@ -3317,6 +3632,170 @@ namespace Mono.CSharp { return true; } + + public bool IsParamsMethodApplicable (EmitContext ec, + ArrayList arguments, int arg_count, + ref MethodBase candidate) + { + return IsParamsMethodApplicable ( + ec, arguments, arg_count, false, ref candidate) || + IsParamsMethodApplicable ( + ec, arguments, arg_count, true, ref candidate); + + + } + + bool IsParamsMethodApplicable (EmitContext ec, + ArrayList arguments, int arg_count, + bool do_varargs, ref MethodBase candidate) + { +#if GMCS_SOURCE + if (!HasTypeArguments && + !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate)) + return false; + + if (TypeManager.IsGenericMethodDefinition (candidate)) + throw new InternalErrorException ("a generic method definition took part in overload resolution"); +#endif + + return IsParamsMethodApplicable ( + ec, arguments, arg_count, candidate, do_varargs); + } + + /// + /// Determines if the candidate method, if a params method, is applicable + /// in its expanded form to the given set of arguments + /// + bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, + int arg_count, MethodBase candidate, + bool do_varargs) + { + ParameterData pd = TypeManager.GetParameterData (candidate); + int pd_count = GetApplicableParametersCount (candidate, pd); + if (pd_count == 0) + return false; + + int count = pd_count - 1; + if (do_varargs) { + if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST) + return false; + if (pd_count != arg_count) + return false; + + if (!(((Argument) arguments [count]).Expr is Arglist)) + return false; + --pd_count; + } else { + if (!pd.HasParams) + return false; + } + + if (count > arg_count) + return false; + + if (pd_count == 1 && arg_count == 0) + return true; + + // + // If we have come this far, the case which + // remains is when the number of parameters is + // less than or equal to the argument count. + // + int argument_index = 0; + Argument a; + for (int i = 0; i < pd_count; ++i) { + + if ((pd.ParameterModifier (i) & Parameter.Modifier.PARAMS) != 0) { + Type element_type = TypeManager.GetElementType (pd.ParameterType (i)); + int params_args_count = arg_count - pd_count; + if (params_args_count < 0) + continue; + + do { + a = (Argument) arguments [argument_index++]; + + if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type)) + return false; + } while (params_args_count-- > 0); + continue; + } + + a = (Argument) arguments [argument_index++]; + + Parameter.Modifier a_mod = a.Modifier & + (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK))); + Parameter.Modifier p_mod = pd.ParameterModifier (i) & + (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK))); + + if (a_mod == p_mod) { + + if (a_mod == Parameter.Modifier.NONE) + if (!Convert.ImplicitConversionExists (ec, + a.Expr, + pd.ParameterType (i))) + return false; + + if ((a_mod & Parameter.Modifier.ISBYREF) != 0) { + Type pt = pd.ParameterType (i); + + if (!pt.IsByRef) + pt = TypeManager.GetReferenceType (pt); + + if (pt != a.Type) + return false; + } + } else + return false; + + } + + return true; + } + + public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc) + { + MemberInfo [] miset; + MethodGroupExpr union; + + if (mg1 == null) { + if (mg2 == null) + return null; + return (MethodGroupExpr) mg2; + } else { + if (mg2 == null) + return (MethodGroupExpr) mg1; + } + + MethodGroupExpr left_set = null, right_set = null; + int length1 = 0, length2 = 0; + + left_set = (MethodGroupExpr) mg1; + length1 = left_set.Methods.Length; + + right_set = (MethodGroupExpr) mg2; + length2 = right_set.Methods.Length; + + ArrayList common = new ArrayList (); + + foreach (MethodBase r in right_set.Methods){ + if (TypeManager.ArrayContainsMethod (left_set.Methods, r)) + common.Add (r); + } + + miset = new MemberInfo [length1 + length2 - common.Count]; + left_set.Methods.CopyTo (miset, 0); + + int k = length1; + + foreach (MethodBase r in right_set.Methods) { + if (!common.Contains (r)) + miset [k++] = r; + } + + union = new MethodGroupExpr (miset, mg1.Type, loc); + + return union; + } static Type MoreSpecific (Type p, Type q) { @@ -3361,26 +3840,6 @@ namespace Mono.CSharp { return null; } - public virtual MethodBase OverloadExtensionResolve (EmitContext ec, ref ArrayList arguments, ref MethodGroupExpr mg, - Expression expr, Location loc) - { - MethodBase method = OverloadResolve (ec, arguments, true, loc); - if (method != null) { - mg = this; - return method; - } - - MemberAccess mexpr = expr as MemberAccess; - if (mexpr != null) { - ExtensionMethodGroupExpr emg = ec.DeclContainer.LookupExtensionMethod (mexpr.Expr.Type, Name); - if (emg != null) { - return OverloadExtensionResolve (ec, ref arguments, ref mg, expr, loc); - } - } - - return OverloadResolve (ec, arguments, false, loc); - } - /// /// Find the Applicable Function Members (7.4.2.1) /// @@ -3397,10 +3856,9 @@ namespace Mono.CSharp { /// that is the best match of me on Arguments. /// /// - public virtual MethodBase OverloadResolve (EmitContext ec, ArrayList Arguments, + public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments, bool may_fail, Location loc) { - MethodBase method = null; bool method_params = false; Type applicable_type = null; int arg_count = 0; @@ -3465,12 +3923,17 @@ namespace Mono.CSharp { nmethods = j; } - int applicable_errors = Report.Errors; - + // + // 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; @@ -3485,19 +3948,29 @@ namespace Mono.CSharp { // Check if candidate is applicable (section 14.4.2.1) // Is candidate applicable in normal form? // - bool is_applicable = Invocation.IsApplicable (ec, this, Arguments, arg_count, ref Methods [i]); + int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i]); - if (!is_applicable && Invocation.IsParamsMethodApplicable (ec, this, Arguments, arg_count, ref Methods [i])) { + if (candidate_rate != 0 && IsParamsMethodApplicable (ec, Arguments, arg_count, ref Methods [i])) { MethodBase candidate = Methods [i]; if (candidate_to_form == null) candidate_to_form = new PtrHashtable (); candidate_to_form [candidate] = candidate; // Candidate is applicable in expanded form - is_applicable = true; + candidate_rate = 0; } - if (!is_applicable) + if (candidate_rate < best_candidate_rate) { + best_candidate_rate = candidate_rate; + best_candidate = Methods [i]; + } + + if (candidate_rate != 0) { + if (msg_recorder != null) + msg_recorder.EndSession (); continue; + } + + msg_recorder = null; candidates.Add (Methods [i]); @@ -3510,69 +3983,56 @@ namespace Mono.CSharp { } } - if (applicable_errors != Report.Errors) + Report.SetMessageRecorder (prev_recorder); + if (msg_recorder != null && msg_recorder.PrintMessages ()) return null; int candidate_top = candidates.Count; if (applicable_type == null) { + if (ec.IsInProbingMode || may_fail) + return null; + // - // Okay so we have failed to find anything so we - // return by providing info about the closest match + // Okay so we have failed to find exact match so we + // return error info about the closest match // - int errors = Report.Errors; - for (int i = 0; i < nmethods; ++i) { - MethodBase c = Methods [i]; - ParameterData pd = TypeManager.GetParameterData (c); - - if (pd.Count != arg_count) - continue; - -#if GMCS_SOURCE - if (!TypeManager.InferTypeArguments (Arguments, ref c)) - continue; - if (TypeManager.IsGenericMethodDefinition (c)) - continue; -#endif - - Invocation.VerifyArgumentsCompat (ec, Arguments, arg_count, - c, false, null, may_fail, loc); - - if (!may_fail && errors == Report.Errors) - throw new InternalErrorException ( - "VerifyArgumentsCompat and IsApplicable do not agree; " + - "likely reason: ImplicitConversion and ImplicitConversionExists have gone out of sync"); + if (best_candidate != null) { + if (CustomErrorHandler != null) { + if (CustomErrorHandler.NoExactMatch (ec, best_candidate)) + return null; + } + + if (TypeManager.IsGenericMethod (best_candidate)) { + 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)); + } else { + VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate, false, null, may_fail, loc); + } - break; + return null; } - if (!may_fail && errors == Report.Errors) { + if (almostMatchedMembers.Count != 0) { + Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor", + null, MemberTypes.Constructor, AllBindingFlags); + return null; + } + + // + // We failed to find any match + // + if (Name == ConstructorInfo.ConstructorName) { + Report.SymbolRelatedToPreviousError (type); + Report.Error (1729, loc, + "The type `{0}' does not contain a constructor that takes `{1}' arguments", + TypeManager.CSharpName (type), arg_count); + } else { string report_name = Name; - if (report_name == ".ctor") + if (report_name == ConstructorInfo.ConstructorName) report_name = TypeManager.CSharpName (DeclaringType); - -#if GMCS_SOURCE - // - // Type inference - // - for (int i = 0; i < Methods.Length; ++i) { - MethodBase c = Methods [i]; - ParameterData pd = TypeManager.GetParameterData (c); - - if (pd.Count != arg_count) - continue; - - if (TypeManager.InferTypeArguments (Arguments, ref c)) - continue; - - Report.Error ( - 411, loc, "The type arguments for " + - "method `{0}' cannot be inferred from " + - "the usage. Try specifying the type " + - "arguments explicitly.", report_name); - return null; - } -#endif Invocation.Error_WrongNumArguments (loc, report_name, arg_count); } @@ -3635,20 +4095,20 @@ namespace Mono.CSharp { // Now we actually find the best method // - method = (MethodBase) candidates [0]; - method_params = candidate_to_form != null && candidate_to_form.Contains (method); + best_candidate = (MethodBase) candidates [0]; + method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate); for (int ix = 1; ix < candidate_top; ix++) { MethodBase candidate = (MethodBase) candidates [ix]; - if (candidate == method) + if (candidate == best_candidate) continue; bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); if (BetterFunction (ec, Arguments, arg_count, candidate, cand_params, - method, method_params)) { - method = candidate; + best_candidate, method_params)) { + best_candidate = candidate; method_params = cand_params; } } @@ -3660,12 +4120,12 @@ namespace Mono.CSharp { for (int ix = 0; ix < candidate_top; ix++) { MethodBase candidate = (MethodBase) candidates [ix]; - if (candidate == method) + if (candidate == best_candidate) continue; bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate); if (!BetterFunction (ec, Arguments, arg_count, - method, method_params, + best_candidate, method_params, candidate, cand_params)) { if (!may_fail) @@ -3675,44 +4135,48 @@ namespace Mono.CSharp { } if (ambiguous != null) { - Report.SymbolRelatedToPreviousError (method); + 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 (method)); - return method; + TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate)); + return this; } // // If the method is a virtual function, pick an override closer to the LHS type. // - if (!IsBase && method.IsVirtual) { - if (TypeManager.IsOverride (method)) + if (!IsBase && best_candidate.IsVirtual) { + if (TypeManager.IsOverride (best_candidate)) throw new InternalErrorException ( - "Should not happen. An 'override' method took part in overload resolution: " + method); + "Should not happen. An 'override' method took part in overload resolution: " + best_candidate); if (candidate_overrides != null) foreach (MethodBase candidate in candidate_overrides) { - if (IsOverride (candidate, method)) - method = candidate; + if (IsOverride (candidate, best_candidate)) + best_candidate = candidate; } } + // We can stop here when probing is on + if (ec.IsInProbingMode) + return this; + // // And now check if the arguments are all // compatible, perform conversions if // necessary etc. and return if everything is // all right // - if (!Invocation.VerifyArgumentsCompat (ec, Arguments, arg_count, method, + if (!VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate, method_params, null, may_fail, loc)) return null; - if (method == null) + if (best_candidate == null) return null; - MethodBase the_method = TypeManager.DropGenericMethodArguments (method); + MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate); #if GMCS_SOURCE if (the_method.IsGenericMethodDefinition && - !ConstraintChecker.CheckConstraints (ec, the_method, method, loc)) + !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc)) return null; #endif @@ -3720,50 +4184,13 @@ namespace Mono.CSharp { if (data != null) data.SetMemberIsUsed (); - return method; - } - - - bool RemoveMethods (bool keep_static) - { - ArrayList smethods = new ArrayList (); - - foreach (MethodBase mb in Methods){ - if (mb.IsStatic == keep_static) - smethods.Add (mb); - } - - if (smethods.Count == 0) - return false; - - Methods = new MethodBase [smethods.Count]; - smethods.CopyTo (Methods, 0); - - return true; + return this; } - /// - /// Removes any instance methods from the MethodGroup, returns - /// false if the resulting set is empty. - /// - public bool RemoveInstanceMethods () - { - return RemoveMethods (true); - } - - /// - /// Removes any static methods from the MethodGroup, returns - /// false if the resulting set is empty. - /// - public bool RemoveStaticMethods () - { - return RemoveMethods (false); - } - public Expression ResolveGeneric (EmitContext ec, TypeArguments args) { #if GMCS_SOURCE - if (args.Resolve (ec) == false) + if (!args.Resolve (ec)) return null; Type[] atypes = args.Arguments; @@ -3774,10 +4201,10 @@ namespace Mono.CSharp { ArrayList list = new ArrayList (); foreach (MethodBase mb in Methods) { MethodInfo mi = mb as MethodInfo; - if ((mi == null) || !mi.IsGenericMethod) + if ((mi == null) || !mb.IsGenericMethod) continue; - Type[] gen_params = mi.GetGenericArguments (); + Type[] gen_params = mb.GetGenericArguments (); if (first == null) { first = mi; @@ -3787,23 +4214,33 @@ namespace Mono.CSharp { if (gen_params.Length != atypes.Length) continue; - list.Add (mi.MakeGenericMethod (atypes)); + mi = mi.MakeGenericMethod (atypes); + list.Add (mi); + +#if MS_COMPATIBLE + // MS implementation throws NotSupportedException for GetParameters + // on unbaked generic method + Parameters p = TypeManager.GetParameterData (mi) as Parameters; + if (p != null) { + p = p.Clone (); + p.InflateTypes (gen_params, atypes); + TypeManager.RegisterMethod (mi, p); + } +#endif } if (list.Count > 0) { - MethodGroupExpr new_mg = new MethodGroupExpr (list, Location); - new_mg.InstanceExpression = InstanceExpression; - new_mg.HasTypeArguments = true; - new_mg.IsBase = IsBase; - return new_mg; + this.Methods = (MethodBase []) list.ToArray (typeof (MethodBase)); + has_type_arguments = true; + return this; } - if (first != null) + if (first != null) { + Report.SymbolRelatedToPreviousError (first); Report.Error ( - 305, loc, "Using the generic method `{0}' " + - "requires {1} type arguments", Name, - first_count.ToString ()); - else + 305, loc, "Using the generic method `{0}' requires `{1}' type arguments", + TypeManager.CSharpSignature (first), first_count.ToString ()); + } else Report.Error ( 308, loc, "The non-generic method `{0}' " + "cannot be used with type arguments", Name); @@ -3813,6 +4250,77 @@ namespace Mono.CSharp { throw new NotImplementedException (); #endif } + + public bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments, + int arg_count, MethodBase method, + bool chose_params_expanded, + Type delegate_type, bool may_fail, Location loc) + { + ParameterData pd = TypeManager.GetParameterData (method); + int param_count = GetApplicableParametersCount (method, pd); + + int j; + int a_idx = 0; + Argument a = null; + int errors = Report.Errors; + for (j = 0; j < param_count; j++) { + Type parameter_type = pd.ParameterType (j); + Parameter.Modifier pm = pd.ParameterModifier (j); + + if (pm == Parameter.Modifier.ARGLIST) { + a = (Argument) Arguments [a_idx]; + if (!(a.Expr is Arglist)) + break; + ++a_idx; + continue; + } + + int params_arg_count = 1; + if (pm == Parameter.Modifier.PARAMS) { + pm = Parameter.Modifier.NONE; + params_arg_count = arg_count - param_count + 1; + if (chose_params_expanded) + parameter_type = TypeManager.GetElementType (parameter_type); + } + + while (params_arg_count > 0) { + a = (Argument) Arguments [a_idx]; + if (pm != a.Modifier) + break; + + if (!TypeManager.IsEqual (a.Type, parameter_type)) { + if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF) + break; + + Expression conv = Convert.ImplicitConversion (ec, a.Expr, parameter_type, loc); + if (conv == null) + break; + + // Update the argument with the implicit conversion + if (a.Expr != conv) + a.Expr = conv; + } + + --params_arg_count; + ++a_idx; + } + if (params_arg_count > 0) + break; + + if (parameter_type.IsPointer && !ec.InUnsafe) { + if (!may_fail) + UnsafeError (loc); + return false; + } + } + + if (a_idx == arg_count) + return true; + + if (!may_fail && Report.Errors == errors) + Error_InvalidArguments (ec, loc, a_idx, method, delegate_type, a, pd); + return false; + } } /// @@ -3913,7 +4421,6 @@ namespace Mono.CSharp { if (t.IsPointer && !ec.InUnsafe) { UnsafeError (loc); - return null; } return base.ResolveMemberAccess (ec, left, loc, original); @@ -3957,7 +4464,7 @@ namespace Mono.CSharp { InstanceExpression.CheckMarshalByRefAccess (); } - if (!in_initializer && !ec.IsFieldInitializer) { + if (!in_initializer && !ec.IsInFieldInitializer) { ObsoleteAttribute oa; FieldBase f = TypeManager.GetField (FieldInfo); if (f != null) { @@ -3983,7 +4490,23 @@ namespace Mono.CSharp { } } } - + + IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo); + if (fb != null) { + if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) { + Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); + } + + if (!(InstanceExpression is LocalVariableReference) && + !(InstanceExpression is This)) { + Report.SymbolRelatedToPreviousError (FieldInfo); + Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", + TypeManager.GetFullNameSignature (FieldInfo)); + } + + return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); + } + // If the instance expression is a local variable or parameter. IVariable var = InstanceExpression as IVariable; if ((var == null) || (var.VariableInfo == null)) @@ -4054,7 +4577,7 @@ namespace Mono.CSharp { if (FieldInfo.IsInitOnly) { // InitOnly fields can only be assigned in constructors or initializers - if (!ec.IsFieldInitializer && !ec.IsConstructor) + if (!ec.IsInFieldInitializer && !ec.IsConstructor) return Report_AssignToReadonly (right_side); if (ec.IsConstructor) { @@ -4145,16 +4668,14 @@ namespace Mono.CSharp { if (!prepared) EmitInstance (ec, false); - if (is_volatile) - ig.Emit (OpCodes.Volatile); - IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo); - if (ff != null) - { + if (ff != null) { ig.Emit (OpCodes.Ldflda, FieldInfo); ig.Emit (OpCodes.Ldflda, ff.Element); - } - else { + } else { + if (is_volatile) + ig.Emit (OpCodes.Volatile); + ig.Emit (OpCodes.Ldfld, FieldInfo); } } @@ -4174,16 +4695,19 @@ namespace Mono.CSharp { bool is_static = (fa & FieldAttributes.Static) != 0; bool is_readonly = (fa & FieldAttributes.InitOnly) != 0; ILGenerator ig = ec.ig; - prepared = prepare_for_load; if (is_readonly && !ec.IsConstructor){ Report_AssignToReadonly (source); return; } - EmitInstance (ec, prepare_for_load); + // + // String concatenation creates a new string instance + // + prepared = prepare_for_load && !(source is StringConcat); + EmitInstance (ec, prepared); - source.Emit (ec); + source.Emit (ec); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!FieldInfo.IsStatic) { @@ -4223,9 +4747,8 @@ namespace Mono.CSharp { FieldBase f = TypeManager.GetField (FieldInfo); if (f != null){ if ((f.ModFlags & Modifiers.VOLATILE) != 0){ - Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter", + Report.Warning (420, 1, loc, "`{0}': A volatile field references will not be treated as volatile", f.GetSignatureForError ()); - return; } if ((mode & AddressOp.Store) != 0) @@ -4462,7 +4985,16 @@ namespace Mono.CSharp { Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly", Name, sig.ToString ()); } - + + public bool IsAccessibleFrom (Type invocation_type, bool lvalue) + { + bool dummy; + MethodInfo accessor = lvalue ? setter : getter; + if (accessor == null && lvalue) + accessor = getter; + return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy); + } + override public Expression DoResolve (EmitContext ec) { if (resolved) @@ -4532,8 +5064,13 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { if (right_side == EmptyExpression.OutAccess) { - Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter", + if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) { + Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter", + PropertyInfo.Name); + } else { + Report.Error (206, loc, "A property or indexer `{0}' may not be passed as `ref' or `out' parameter", GetSignatureForError ()); + } return null; } @@ -4618,7 +5155,7 @@ namespace Mono.CSharp { } } - Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false); + Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false); if (leave_copy) { ec.ig.Emit (OpCodes.Dup); @@ -4636,10 +5173,15 @@ namespace Mono.CSharp { { Expression my_source = source; - prepared = prepare_for_load; - - if (prepared) { + if (prepare_for_load) { + if (source is StringConcat) + EmitInstance (ec, false); + else + prepared = true; + source.Emit (ec); + + prepared = true; if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!is_static) { @@ -4649,17 +5191,15 @@ namespace Mono.CSharp { } } else if (leave_copy) { source.Emit (ec); - if (!is_static) { - temp = new LocalTemporary (this.Type); - temp.Store (ec); - } + temp = new LocalTemporary (this.Type); + temp.Store (ec); my_source = temp; } - + ArrayList args = new ArrayList (1); args.Add (new Argument (my_source, Argument.AType.Expression)); - Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared); + Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared); if (temp != null) { temp.Emit (ec); @@ -4673,6 +5213,7 @@ namespace Mono.CSharp { /// public class EventExpr : MemberExpr { public readonly EventInfo EventInfo; + public bool IsBase; bool is_static; MethodInfo add_accessor, remove_accessor; @@ -4763,6 +5304,11 @@ namespace Mono.CSharp { if (InstanceExpression == null) return false; + if (IsBase && add_accessor.IsAbstract) { + Error_CannotCallAbstractBase(TypeManager.CSharpSignature(add_accessor)); + return false; + } + // // This is using the same mechanism as the CS1540 check in PropertyExpr. // However, in the Event case, we reported a CS0122 instead. @@ -4778,6 +5324,13 @@ namespace Mono.CSharp { return true; } + public bool IsAccessibleFrom (Type invocation_type) + { + bool dummy; + return IsAccessorAccessible (invocation_type, add_accessor, out dummy) && + IsAccessorAccessible (invocation_type, remove_accessor, out dummy); + } + public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { return DoResolve (ec); @@ -4829,10 +5382,10 @@ namespace Mono.CSharp { if (source_del.IsAddition) Invocation.EmitCall ( - ec, false, IsStatic, InstanceExpression, add_accessor, args, loc); + ec, IsBase, InstanceExpression, add_accessor, args, loc); else Invocation.EmitCall ( - ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc); + ec, IsBase, InstanceExpression, remove_accessor, args, loc); } } @@ -4905,5 +5458,76 @@ namespace Mono.CSharp { EmitLoadAddress (ec); } } - + + /// + /// Handles `var' contextual keyword; var becomes a keyword only + /// if no type called var exists in a variable scope + /// + public class VarExpr : SimpleName + { + // Used for error reporting only + ArrayList initializer; + + public VarExpr (string name, Location loc) + : base (name, loc) + { + } + + public ArrayList VariableInitializer { + set { + this.initializer = value; + } + } + + public override Expression DoResolveLValue (EmitContext 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 == TypeManager.anonymous_method_type) { + Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'", + right_side.GetSignatureForError ()); + return null; + } + + eclass = ExprClass.Variable; + return this; + } + + protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec) + { + if (ec is FieldBase) { + Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration"); + return; + } + + base.Error_TypeOrNamespaceNotFound (ec); + } + + public override TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent) + { + TypeExpr te = base.ResolveAsContextualType (rc, true); + if (te != null) + return te; + + if (initializer == null) + return null; + + // TODO: refactor, the error is reported too many times + if (initializer.Count > 1) { + Location loc = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [1]).Location; + Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators"); + return null; + } + + Expression variable_initializer = ((Mono.CSharp.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"); + return null; + } + + return null; + } + } }