X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fecore.cs;h=cd22984ab77045a6eefa192503f2869ea933ff82;hb=e0df8328d11d79623c1b0369cf15544b26a18db0;hp=91f013ef80d421d3dc1b8cd8c1d851100b0dd95e;hpb=f73e0d5c67f0d26e85b92fc4b75fc48783f20d64;p=mono.git diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index 91f013ef80d..cd22984ab77 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -3,6 +3,7 @@ // // Author: // Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) // // (C) 2001, 2002, 2003 Ximian, Inc. // @@ -128,14 +129,20 @@ namespace Mono.CSharp { /// public void Error (int error, string s) { - if (loc.IsNull) - Report.Error (error, s); - else - Report.Error (error, loc, s); + Report.Error (error, loc, s); } - // Not nice but we have broken hierarchy - public virtual void CheckMarshallByRefAccess (Type container) {} + // Not nice but we have broken hierarchy. + public virtual void CheckMarshalByRefAccess () + { + } + + public virtual bool GetAttributableValue (Type valueType, out object value) + { + Attribute.Error_AttributeArgumentNotValid (loc); + value = null; + return false; + } public virtual string GetSignatureForError () { @@ -148,14 +155,18 @@ namespace Mono.CSharp { must_do_cs1540_check = false; // by default we do not check for this + if (ma == MethodAttributes.Public) + return true; + // // If only accessible to the current class or children // if (ma == MethodAttributes.Private) - return invocation_type == mi.DeclaringType || + return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) || TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType); - if (mi.DeclaringType.Assembly == invocation_type.Assembly) { + if (mi.DeclaringType.Assembly == invocation_type.Assembly || + TypeManager.IsFriendAssembly (mi.DeclaringType.Assembly)) { if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) return true; } else { @@ -165,17 +176,11 @@ namespace Mono.CSharp { // Family and FamANDAssem require that we derive. // FamORAssem requires that we derive if in different assemblies. - if (ma == MethodAttributes.Family || - ma == MethodAttributes.FamANDAssem || - ma == MethodAttributes.FamORAssem) { - if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType)) - return false; + if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType)) + return false; - if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType)) - must_do_cs1540_check = true; - - return true; - } + if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType)) + must_do_cs1540_check = true; return true; } @@ -218,7 +223,7 @@ 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 (EmitContext ec, bool silent) + public virtual FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { return null; } @@ -228,7 +233,34 @@ namespace Mono.CSharp { // value will be returned if the expression is not a type // reference // - public TypeExpr ResolveAsTypeTerminal (EmitContext ec, bool silent) + public virtual TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) + { + TypeExpr te = ResolveAsBaseTerminal (ec, silent); + if (te == null) + return null; + + if (!silent) { + ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type); + if (obsolete_attr != null && !ec.IsInObsoleteScope) { + AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location); + } + } + + // Constrains don't need to be checked for overrides + GenericMethod gm = ec.GenericDeclContainer as GenericMethod; + if (gm != null && (gm.ModFlags & Modifiers.OVERRIDE) != 0) { + te.loc = loc; + return te; + } + + ConstructedType ct = te as ConstructedType; + if ((ct != null) && !ct.CheckConstraints (ec)) + return null; + + return te; + } + + public TypeExpr ResolveAsBaseTerminal (IResolveContext ec, bool silent) { int errors = Report.Errors; @@ -245,7 +277,8 @@ namespace Mono.CSharp { TypeExpr te = fne as TypeExpr; - if (!te.CheckAccessLevel (ec.DeclSpace)) { + if (!te.CheckAccessLevel (ec.DeclContainer)) { + Report.SymbolRelatedToPreviousError (te.Type); ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type)); return null; } @@ -261,21 +294,32 @@ namespace Mono.CSharp { protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container) { - 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)", + 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), TypeManager.CSharpName (qualifier), TypeManager.CSharpName (container)); } + protected void Error_CannotAssign (string to, string roContext) + { + Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", + to, roContext); + } + + public static void Error_VoidInvalidInTheContext (Location loc) + { + Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); + } + public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl) { - if (Type.Name == target.Name){ + if (Type.FullName == target.FullName){ Report.ExtraInformation (loc, String.Format ( "The type {0} has two conflicting definitions, one comes from {1} and the other from {2}", - Type.Name, Type.Assembly.FullName, target.Assembly.FullName)); + Type.FullName, Type.Assembly.FullName, target.Assembly.FullName)); } @@ -294,9 +338,9 @@ namespace Mono.CSharp { return; } - if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) { + if (Type != TypeManager.string_type && this is Constant && !(this is EmptyConstantCast)) { Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", - GetSignatureForError (), TypeManager.CSharpName (target)); + ((Constant)(this)).GetValue ().ToString (), TypeManager.CSharpName (target)); return; } @@ -312,28 +356,34 @@ namespace Mono.CSharp { TypeManager.CSharpName (type), name); } - ResolveFlags ExprClassToResolveFlags () + protected static void Error_ValueAssignment (Location loc) { - switch (eclass) { - case ExprClass.Type: - case ExprClass.Namespace: - return ResolveFlags.Type; + Report.Error (131, loc, "The left-hand side of an assignment must be a variable, a property or an indexer"); + } - case ExprClass.MethodGroup: - return ResolveFlags.MethodGroup; + ResolveFlags ExprClassToResolveFlags + { + get { + switch (eclass) { + case ExprClass.Type: + case ExprClass.Namespace: + return ResolveFlags.Type; - case ExprClass.Value: - case ExprClass.Variable: - case ExprClass.PropertyAccess: - case ExprClass.EventAccess: - case ExprClass.IndexerAccess: - return ResolveFlags.VariableOrValue; + case ExprClass.MethodGroup: + return ResolveFlags.MethodGroup; - default: - throw new Exception ("Expression " + GetType () + - " ExprClass is Invalid after resolve"); - } + case ExprClass.Value: + case ExprClass.Variable: + case ExprClass.PropertyAccess: + case ExprClass.EventAccess: + case ExprClass.IndexerAccess: + return ResolveFlags.VariableOrValue; + default: + throw new Exception ("Expression " + GetType () + + " ExprClass is Invalid after resolve"); + } + } } /// @@ -349,28 +399,27 @@ namespace Mono.CSharp { if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) return ResolveAsTypeStep (ec, false); - bool old_do_flow_analysis = ec.DoFlowAnalysis; - bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis; + bool do_flow_analysis = ec.DoFlowAnalysis; + bool omit_struct_analysis = ec.OmitStructFlowAnalysis; if ((flags & ResolveFlags.DisableFlowAnalysis) != 0) - ec.DoFlowAnalysis = false; + do_flow_analysis = false; if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0) - ec.OmitStructFlowAnalysis = true; + omit_struct_analysis = true; Expression e; - bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate; - if (this is SimpleName) - e = ((SimpleName) this).DoResolve (ec, intermediate); - - else - e = DoResolve (ec); - - ec.DoFlowAnalysis = old_do_flow_analysis; - ec.OmitStructFlowAnalysis = old_omit_struct_analysis; + 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); + } + } if (e == null) return null; - if ((flags & e.ExprClassToResolveFlags ()) == 0) { + if ((flags & e.ExprClassToResolveFlags) == 0) { e.Error_UnexpectedKind (flags, loc); return null; } @@ -409,17 +458,6 @@ namespace Mono.CSharp { if (c != null) return c; - EmptyCast empty = e as EmptyCast; - if (empty != null) { - c = empty.Child as Constant; - if (c != null) { - // TODO: not sure about this maybe there is easier way how to use EmptyCast - if (e.Type.IsEnum) - c.Type = e.Type; - - return c; - } - } Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ()); return null; } @@ -435,32 +473,43 @@ namespace Mono.CSharp { public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc) { int errors = Report.Errors; + bool out_access = right_side == EmptyExpression.OutAccess; + Expression e = DoResolveLValue (ec, right_side); + if (e != null && out_access && !(e is IMemoryLocation)) { + // FIXME: There's no problem with correctness, the 'Expr = null' handles that. + // Enabling this 'throw' will "only" result in deleting useless code elsewhere, + + //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " + + // e.GetType () + " " + e.GetSignatureForError ()); + e = null; + } + if (e == null) { - if (errors == Report.Errors) - Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer"); + if (errors == Report.Errors) { + if (out_access) + Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); + else + Error_ValueAssignment (loc); + } return null; } - if (e != null){ - if (e.eclass == ExprClass.Invalid) - throw new Exception ("Expression " + e + - " ExprClass is Invalid after resolve"); + if (e.eclass == ExprClass.Invalid) + throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); - if (e.eclass == ExprClass.MethodGroup) { - ((MethodGroupExpr) e).ReportUsageError (); - return null; - } - - if (e.type == null) - throw new Exception ("Expression " + e + - " did not set its type after Resolve"); + if (e.eclass == ExprClass.MethodGroup) { + ((MethodGroupExpr) e).ReportUsageError (); + return null; } + if ((e.type == null) && !(e is ConstructedType)) + throw new Exception ("Expression " + e + " did not set its type after Resolve"); + return e; } - + /// /// Emits the code for the expression /// @@ -550,14 +599,14 @@ namespace Mono.CSharp { /// Returns a fully formed expression after a MemberLookup /// /// - public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc) + public static Expression ExprClassFromMemberInfo (Type containerType, MemberInfo mi, Location loc) { if (mi is EventInfo) return new EventExpr ((EventInfo) mi, loc); else if (mi is FieldInfo) return new FieldExpr ((FieldInfo) mi, loc); else if (mi is PropertyInfo) - return new PropertyExpr (ec, (PropertyInfo) mi, loc); + return new PropertyExpr (containerType, (PropertyInfo) mi, loc); else if (mi is Type){ return new TypeExpression ((System.Type) mi, loc); } @@ -595,10 +644,10 @@ namespace Mono.CSharp { // FIXME: Potential optimization, have a static ArrayList // - public static Expression MemberLookup (EmitContext ec, Type queried_type, string name, + public static Expression MemberLookup (Type container_type, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) { - return MemberLookup (ec, ec.ContainerType, null, queried_type, name, mt, bf, loc); + return MemberLookup (container_type, null, queried_type, name, mt, bf, loc); } // @@ -606,7 +655,7 @@ namespace Mono.CSharp { // `qualifier_type' or null to lookup members in the current class. // - public static Expression MemberLookup (EmitContext ec, Type container_type, + public static Expression MemberLookup (Type container_type, Type qualifier_type, Type queried_type, string name, MemberTypes mt, BindingFlags bf, Location loc) @@ -619,15 +668,60 @@ namespace Mono.CSharp { if (mi == null) return null; - int count = mi.Length; + if (mi.Length > 1) { + bool is_interface = qualifier_type != null && qualifier_type.IsInterface; + MemberInfo non_method = null; + ArrayList methods = new ArrayList (2); + + foreach (MemberInfo m in mi) { + if (m is MethodBase) { + methods.Add (m); + continue; + } + + if (non_method == null) { + non_method = m; + continue; + } + + Report.SymbolRelatedToPreviousError (m); + Report.SymbolRelatedToPreviousError (non_method); + Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", + TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (non_method)); + return null; + } + + if (methods.Count == 0) + return null; + + if (non_method != null) { + MethodBase method = (MethodBase) 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, loc); + } if (mi [0] is MethodBase) return new MethodGroupExpr (mi, loc); - if (count > 1) - return null; - - return ExprClassFromMemberInfo (ec, mi [0], loc); + return ExprClassFromMemberInfo (container_type, mi [0], loc); } public const MemberTypes AllMemberTypes = @@ -643,24 +737,24 @@ namespace Mono.CSharp { BindingFlags.Static | BindingFlags.Instance; - public static Expression MemberLookup (EmitContext ec, Type queried_type, + public static Expression MemberLookup (Type container_type, Type queried_type, string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, null, queried_type, name, + return MemberLookup (container_type, null, queried_type, name, AllMemberTypes, AllBindingFlags, loc); } - public static Expression MemberLookup (EmitContext ec, Type qualifier_type, + public static Expression MemberLookup (Type container_type, Type qualifier_type, Type queried_type, string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, + return MemberLookup (container_type, qualifier_type, queried_type, name, AllMemberTypes, AllBindingFlags, loc); } public static Expression MethodLookup (EmitContext ec, Type queried_type, string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, null, queried_type, name, + return MemberLookup (ec.ContainerType, null, queried_type, name, MemberTypes.Method, AllBindingFlags, loc); } @@ -686,16 +780,16 @@ namespace Mono.CSharp { int errors = Report.Errors; - e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc); + 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, qualifier_type, queried_type, name, null, true, loc); + MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc); return e; } - public static void MemberLookupFailed (EmitContext ec, Type qualifier_type, + 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) @@ -718,16 +812,16 @@ namespace Mono.CSharp { if (qualifier_type == null) { Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", TypeManager.CSharpName (m.DeclaringType), - TypeManager.CSharpName (ec.ContainerType)); + TypeManager.CSharpName (container_type)); - } else if (qualifier_type != ec.ContainerType && - TypeManager.IsNestedFamilyAccessible (ec.ContainerType, declaring_type)) { + } else if (qualifier_type != container_type && + TypeManager.IsNestedFamilyAccessible (container_type, declaring_type)) { // 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.ContainerType and the lookup succeeds with the latter one, // then we are in this situation. - Error_CannotAccessProtected (loc, m, qualifier_type, ec.ContainerType); + Error_CannotAccessProtected (loc, m, qualifier_type, container_type); } else { ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m)); } @@ -736,9 +830,14 @@ namespace Mono.CSharp { return; } - MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type, - AllMemberTypes, AllBindingFlags | - BindingFlags.NonPublic, name, null); + MemberInfo[] lookup = null; + if (queried_type == null) { + class_name = "global::"; + } else { + lookup = TypeManager.MemberLookup (queried_type, null, queried_type, + AllMemberTypes, AllBindingFlags | + BindingFlags.NonPublic, name, null); + } if (lookup == null) { if (!complain_if_none_found) @@ -752,14 +851,30 @@ namespace Mono.CSharp { return; } + 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; + } + } + MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor, - BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null); + 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; } + Report.SymbolRelatedToPreviousError (lookup [0]); ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0])); } @@ -767,7 +882,7 @@ namespace Mono.CSharp { /// Returns an expression that can be used to invoke operator true /// on the expression if it exists. /// - static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc) + static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, true, loc); } @@ -776,16 +891,21 @@ namespace Mono.CSharp { /// Returns an expression that can be used to invoke operator false /// on the expression if it exists. /// - static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc) + static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc) { return GetOperatorTrueOrFalse (ec, e, false, loc); } - static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc) + static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc) { MethodBase method; Expression 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, e.Type, is_true ? "op_True" : "op_False", loc); if (operator_group == null) return null; @@ -862,16 +982,16 @@ namespace Mono.CSharp { /// /// Reports that we were expecting `expr' to be of class `expected' /// - public void Error_UnexpectedKind (EmitContext ec, string expected, Location loc) + public void Error_UnexpectedKind (DeclSpace ds, string expected, Location loc) { - Error_UnexpectedKind (ec, expected, ExprClassName, loc); + Error_UnexpectedKind (ds, expected, ExprClassName, loc); } - public void Error_UnexpectedKind (EmitContext ec, string expected, string was, Location loc) + public void Error_UnexpectedKind (DeclSpace ds, string expected, string was, Location loc) { string name = GetSignatureForError (); - if (ec != null) - name = ec.DeclSpace.GetSignatureForError () + '.' + name; + if (ds != null) + name = ds.GetSignatureForError () + '.' + name; Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", name, was, expected); @@ -951,11 +1071,11 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldind_Ref); else LoadFromPtr (ig, TypeManager.EnumToUnderlying (t)); - } else if (t.IsValueType) + } else if (t.IsValueType || TypeManager.IsGenericParameter (t)) ig.Emit (OpCodes.Ldobj, t); else if (t.IsPointer) ig.Emit (OpCodes.Ldind_I); - else + else ig.Emit (OpCodes.Ldind_Ref); } @@ -982,7 +1102,7 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Stind_I1); else if (type == TypeManager.intptr_type) ig.Emit (OpCodes.Stind_I); - else if (type.IsValueType) + else if (type.IsValueType || TypeManager.IsGenericParameter (type)) ig.Emit (OpCodes.Stobj, type); else ig.Emit (OpCodes.Stind_Ref); @@ -1033,22 +1153,20 @@ namespace Mono.CSharp { { Expression target; - bool old_checked = ec.CheckState; - ec.CheckState = true; - - target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc); - if (target == null){ - target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc); - if (target == null){ + using (ec.With (EmitContext.Flags.CheckState, true)) { + target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc); + if (target == null) + target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc); + if (target == null) target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc); - if (target == null){ - target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc); - if (target == null) - source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false); - } + if (target == null) + target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc); + + if (target == null) { + source.Error_ValueCannotBeConverted (loc, TypeManager.int32_type, false); + return null; } - } - ec.CheckState = old_checked; + } // // Only positive constants are allowed at compile time @@ -1120,13 +1238,7 @@ namespace Mono.CSharp { /// /// public class EmptyCast : Expression { - protected Expression child; - - public Expression Child { - get { - return child; - } - } + protected readonly Expression child; public EmptyCast (Expression child, Type return_type) { @@ -1148,12 +1260,75 @@ namespace Mono.CSharp { { child.Emit (ec); } + + public override bool GetAttributableValue (Type valueType, out object value) + { + return child.GetAttributableValue (valueType, out value); + } + + } + + /// + /// Performs a cast using an operator (op_Explicit or op_Implicit) + /// + public class OperatorCast : EmptyCast { + MethodInfo conversion_operator; + bool find_explicit; + + public OperatorCast (Expression child, Type target_type) : this (child, target_type, false) {} + + public OperatorCast (Expression child, Type target_type, bool find_explicit) + : base (child, target_type) + { + this.find_explicit = find_explicit; + } + + // Returns the implicit operator that converts from + // 'child.Type' to our target type (type) + MethodInfo 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); + + if (mi == null){ + mi = TypeManager.MemberLookup (type, type, type, MemberTypes.Method, + BindingFlags.Static | BindingFlags.Public, operator_name, null); + } + + foreach (MethodInfo oper in mi) { + ParameterData pd = TypeManager.GetParameterData (oper); + + if (pd.ParameterType (0) == child.Type && oper.ReturnType == type) + return oper; + } + + return null; + + + } + public override void Emit (EmitContext ec) + { + ILGenerator ig = ec.ig; + + child.Emit (ec); + conversion_operator = GetConversionOperator (find_explicit); + + if (conversion_operator == null) + throw new InternalErrorException ("Outer conversion routine is out of sync"); + + ig.Emit (OpCodes.Call, conversion_operator); + } + } + /// /// This is a numeric cast to a Decimal /// public class CastToDecimal : EmptyCast { - MethodInfo conversion_operator; public CastToDecimal (Expression child) @@ -1241,69 +1416,63 @@ namespace Mono.CSharp { } } - // + + // + // Constant specialization of EmptyCast. // We need to special case this since an empty cast of - // a NullLiteral is still a Constant + // a constant is still a constant. // - public class NullCast : Constant { - public Constant child; - - public NullCast (Constant child, Type return_type): - base (Location.Null) + public class EmptyConstantCast : Constant + { + public readonly Constant child; + + public EmptyConstantCast(Constant child, Type type) + : base (child.Location) { eclass = child.eclass; - type = return_type; this.child = child; + this.type = type; } - override public string AsString () + public override string AsString () { - return "null"; + return child.AsString (); } public override object GetValue () { - return null; + return child.GetValue (); } - public override Expression DoResolve (EmitContext ec) + public override Constant Reduce (bool inCheckedContext, Type target_type) { - // This should never be invoked, we are born in fully - // initialized state. - - return this; + return child.Reduce (inCheckedContext, target_type); } - public override void Emit (EmitContext ec) + public override Constant Increment () { - child.Emit (ec); + return child.Increment (); } - public override Constant Increment () + public override bool IsDefaultValue { - throw new NotSupportedException (); + get { return child.IsDefaultValue; } } - public override bool IsDefaultValue { - get { - return true; - } + public override bool IsNegative + { + get { return child.IsNegative; } } - public override bool IsNegative { - get { - return false; - } + public override void Emit (EmitContext ec) + { + child.Emit (ec); } - public override Constant Reduce (EmitContext ec, Type target_type) + public override Constant ToType (Type type) { - if (type == target_type) - return child.Reduce (ec, target_type); - - return null; + return child.ToType (type); } - } @@ -1334,6 +1503,12 @@ namespace Mono.CSharp { Child.Emit (ec); } + public override bool GetAttributableValue (Type valueType, out object value) + { + value = GetTypedValue (); + return true; + } + public override string GetSignatureForError() { return TypeManager.CSharpName (Type); @@ -1410,15 +1585,15 @@ namespace Mono.CSharp { } } - public override Constant Reduce(EmitContext ec, Type target_type) + public override Constant Reduce(bool inCheckedContext, Type target_type) { if (Child.Type == target_type) return Child; - return Child.Reduce (ec, target_type); + return Child.Reduce (inCheckedContext, target_type); } - public override Constant ToType (Type type, Location loc) + public override Constant ToType (Type type) { if (Type == type) { // This is workaround of mono bug. It can be removed when the latest corlib spreads enough @@ -1426,16 +1601,15 @@ namespace Mono.CSharp { return this; if (type.UnderlyingSystemType != Child.Type) - Child = Child.ToType (type.UnderlyingSystemType, loc); + Child = Child.ToType (type.UnderlyingSystemType); return this; } - if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){ - Error_ValueCannotBeConverted (loc, type, false); + if (!Convert.ImplicitStandardConversionExists (this, type)){ return null; } - return Child.ToType (type, loc); + return Child.ToType (type); } } @@ -1484,15 +1658,29 @@ namespace Mono.CSharp { return this; } + public override Expression DoResolveLValue (EmitContext 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"); + return base.DoResolveLValue (ec, right_side); + } + public override void Emit (EmitContext ec) { Type t = type; ILGenerator ig = ec.ig; base.Emit (ec); - ig.Emit (OpCodes.Unbox, t); +#if GMCS_SOURCE + if (t.IsGenericParameter || t.IsGenericType && t.IsValueType) + ig.Emit (OpCodes.Unbox_Any, t); + else +#endif + { + ig.Emit (OpCodes.Unbox, t); - LoadFromPtr (ig, t); + LoadFromPtr (ig, t); + } } } @@ -1773,9 +1961,16 @@ namespace Mono.CSharp { { base.Emit (ec); - ec.ig.Emit (OpCodes.Castclass, type); - } - + if (TypeManager.IsGenericParameter (child.Type)) + ec.ig.Emit (OpCodes.Box, child.Type); + +#if GMCS_SOURCE + if (type.IsGenericParameter) + ec.ig.Emit (OpCodes.Unbox_Any, type); + else +#endif + ec.ig.Emit (OpCodes.Castclass, type); + } } /// @@ -1784,6 +1979,7 @@ namespace Mono.CSharp { /// public class SimpleName : Expression { public string Name; + public readonly TypeArguments Arguments; bool in_transit; public SimpleName (string name, Location l) @@ -1792,27 +1988,68 @@ namespace Mono.CSharp { loc = l; } + public SimpleName (string name, TypeArguments args, Location l) + { + Name = name; + Arguments = args; + loc = l; + } + + public SimpleName (string name, TypeParameter[] type_params, Location l) + { + Name = name; + loc = l; + + Arguments = new TypeArguments (l); + foreach (TypeParameter type_param in type_params) + Arguments.Add (new TypeParameterExpr (type_param, l)); + } + + public static string RemoveGenericArity (string name) + { + int start = 0; + StringBuilder sb = new StringBuilder (); + while (start < name.Length) { + int pos = name.IndexOf ('`', start); + if (pos < 0) { + sb.Append (name.Substring (start)); + break; + } + + sb.Append (name.Substring (start, pos-start)); + + pos++; + while ((pos < name.Length) && Char.IsNumber (name [pos])) + pos++; + + start = pos; + } + + return sb.ToString (); + } + + public SimpleName GetMethodGroup () + { + return new SimpleName (RemoveGenericArity (Name), Arguments, loc); + } + public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) { if (ec.IsFieldInitializer) Report.Error (236, l, "A field initializer cannot reference the nonstatic field, method, or property `{0}'", name); - else { - if (name.LastIndexOf ('.') > 0) - name = name.Substring (name.LastIndexOf ('.') + 1); - + else Report.Error ( 120, l, "`{0}': An object reference is required for the nonstatic field, method or property", name); - } } public bool IdenticalNameAndTypeName (EmitContext ec, Expression resolved_to, Location loc) { return resolved_to != null && resolved_to.Type != null && resolved_to.Type.Name == Name && - (ec.DeclSpace.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null); + (ec.DeclContainer.LookupType (Name, loc, /* ignore_cs0104 = */ true) != null); } public override Expression DoResolve (EmitContext ec) @@ -1831,23 +2068,110 @@ namespace Mono.CSharp { return SimpleNameResolve (ec, null, intermediate); } - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + private bool IsNestedChild (Type t, Type parent) { - int errors = Report.Errors; - FullNamedExpression fne = ec.DeclSpace.LookupType (Name, loc, /*ignore_cs0104=*/ false); + if (parent == null) + return false; + + while (parent != null) { + parent = TypeManager.DropGenericTypeArguments (parent); + if (TypeManager.IsNestedChildOf (t, parent)) + return true; + + parent = parent.BaseType; + } + + return false; + } + + FullNamedExpression ResolveNested (IResolveContext ec, Type t) + { + if (!TypeManager.IsGenericTypeDefinition (t)) + return null; + + DeclSpace ds = ec.DeclContainer; + while (ds != null) { + if (IsNestedChild (t, ds.TypeBuilder)) + break; + + ds = ds.Parent; + } + + if (ds == null) + return null; + + Type[] gen_params = TypeManager.GetTypeArguments (t); + + int arg_count = Arguments != null ? Arguments.Count : 0; + + for (; (ds != null) && ds.IsGeneric; ds = ds.Parent) { + if (arg_count + ds.CountTypeParameters == gen_params.Length) { + TypeArguments new_args = new TypeArguments (loc); + foreach (TypeParameter param in ds.TypeParameters) + new_args.Add (new TypeParameterExpr (param, loc)); + + if (Arguments != null) + new_args.Add (Arguments); + + return new ConstructedType (t, new_args, loc); + } + } + + return null; + } + + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) + { + FullNamedExpression fne = ec.GenericDeclContainer.LookupGeneric (Name, loc); if (fne != null) + return fne.ResolveAsTypeStep (ec, silent); + + int errors = Report.Errors; + fne = ec.DeclContainer.LookupType (Name, 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 (Arguments != null) { + ConstructedType ct = new ConstructedType (fne, Arguments, loc); + return ct.ResolveAsTypeStep (ec, false); + } + return fne; + } + + if (silent || errors != Report.Errors) + return null; + + MemberCore mc = ec.DeclContainer.GetDefinition (Name); + if (mc != null) { + Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc); + return null; + } + + string ns = ec.DeclContainer.NamespaceEntry.NS.Name; + string fullname = (ns.Length > 0) ? ns + "." + Name : Name; + foreach (Assembly a in RootNamespace.Global.Assemblies) { + Type type = a.GetType (fullname); + if (type != null) { + Report.SymbolRelatedToPreviousError (type); + Expression.ErrorIsInaccesible (loc, fullname); + return null; + } + } - if (silent || errors != Report.Errors) + Type t = ec.DeclContainer.NamespaceEntry.NS.LookForAnyGenericType (Name); + if (t != null) { + Namespace.Error_InvalidNumberOfTypeArguments (t, loc); return null; - - MemberCore mc = ec.DeclSpace.GetDefinition (Name); - if (mc != null) { - Error_UnexpectedKind (ec, "type", GetMemberType (mc), loc); - } else { - NamespaceEntry.Error_NamespaceNotFound (loc, Name); } + NamespaceEntry.Error_NamespaceNotFound (loc, Name); return null; } @@ -1913,6 +2237,13 @@ namespace Mono.CSharp { if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ + if (Arguments != null) { + Report.Error (307, loc, + "The variable `{0}' cannot be used with type arguments", + Name); + return null; + } + LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc); if (right_side != null) { return var.ResolveLValue (ec, right_side, loc); @@ -1926,6 +2257,13 @@ namespace Mono.CSharp { ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc); if (pref != null) { + if (Arguments != null) { + Report.Error (307, loc, + "The variable `{0}' cannot be used with type arguments", + Name); + return null; + } + if (right_side != null) return pref.ResolveLValue (ec, right_side, loc); else @@ -1937,14 +2275,14 @@ namespace Mono.CSharp { // Stage 2: Lookup members // - DeclSpace lookup_ds = ec.DeclSpace; + DeclSpace lookup_ds = ec.DeclContainer; Type almost_matched_type = null; ArrayList almost_matched = null; do { if (lookup_ds.TypeBuilder == null) break; - e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc); + e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc); if (e != null) break; @@ -1955,9 +2293,9 @@ namespace Mono.CSharp { lookup_ds =lookup_ds.Parent; } while (lookup_ds != null); - + if (e == null && ec.ContainerType != null) - e = MemberLookup (ec, ec.ContainerType, Name, loc); + e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc); if (e == null) { if (almost_matched == null && almostMatchedMembers.Count > 0) { @@ -1972,12 +2310,18 @@ namespace Mono.CSharp { almostMatchedMembers = almost_matched; if (almost_matched_type == null) almost_matched_type = ec.ContainerType; - MemberLookupFailed (ec, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclSpace.Name, true, loc); + MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc); return null; } - if (e is TypeExpr) - return e; + if (e is TypeExpr) { + if (Arguments == null) + return e; + + ConstructedType ct = new ConstructedType ( + (FullNamedExpression) e, Arguments, loc); + return ct.ResolveAsTypeStep (ec, false); + } if (e is MemberExpr) { MemberExpr me = (MemberExpr) e; @@ -2017,10 +2361,18 @@ namespace Mono.CSharp { if (me == null) return e; - if (!me.IsStatic && + if (Arguments != null) { + MethodGroupExpr mg = me as MethodGroupExpr; + if (mg == null) + return null; + + return mg.ResolveGeneric (ec, Arguments); + } + + if (!me.IsStatic && (me.InstanceExpression != null) && TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && me.InstanceExpression.Type != me.DeclaringType && - !me.InstanceExpression.Type.IsSubclassOf (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)); @@ -2044,7 +2396,7 @@ namespace Mono.CSharp { Error (103, "The name `" + Name + "' does not exist in the class `" + - ec.DeclSpace.Name + "'"); + ec.DeclContainer.Name + "'"); } public override string ToString () @@ -2063,7 +2415,7 @@ namespace Mono.CSharp { /// section 10.8.1 (Fully Qualified Names). /// public abstract class FullNamedExpression : Expression { - public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { return this; } @@ -2077,7 +2429,7 @@ namespace Mono.CSharp { /// Expression that evaluates to a type /// public abstract class TypeExpr : FullNamedExpression { - override public FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + override public FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent) { TypeExpr t = DoResolveAsTypeStep (ec); if (t == null) @@ -2135,23 +2487,7 @@ namespace Mono.CSharp { return true; } - public abstract TypeExpr DoResolveAsTypeStep (EmitContext ec); - - public Type ResolveType (EmitContext ec) - { - TypeExpr t = ResolveAsTypeTerminal (ec, false); - if (t == null) - return null; - - if (ec.TestObsoleteMethodUsage) { - ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (t.Type); - if (obsolete_attr != null) { - AttributeTester.Report_ObsoleteMessage (obsolete_attr, Name, Location); - } - } - - return t.Type; - } + protected abstract TypeExpr DoResolveAsTypeStep (IResolveContext ec); public abstract string Name { get; @@ -2188,7 +2524,12 @@ namespace Mono.CSharp { loc = l; } - public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + { + return this; + } + + public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) { return this; } @@ -2207,20 +2548,27 @@ namespace Mono.CSharp { /// by the parser to setup the core types. A TypeLookupExpression is always /// classified as a type. /// - public class TypeLookupExpression : TypeExpr { - string name; + public sealed class TypeLookupExpression : TypeExpr { + readonly string name; public TypeLookupExpression (string name) { this.name = name; + eclass = ExprClass.Type; } - static readonly char [] dot_array = { '.' }; - public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + public override TypeExpr ResolveAsTypeTerminal (IResolveContext ec, bool silent) { - if (type != null) - return this; + // It's null for corlib compilation only + if (type == null) + return DoResolveAsTypeStep (ec); + + return this; + } + static readonly char [] dot_array = { '.' }; + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + { // 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; @@ -2230,7 +2578,7 @@ namespace Mono.CSharp { lookup_name = name.Substring (0, pos); } - FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclSpace, lookup_name, Location.Null); + FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null); if (resolved != null && rest != null) { // Now handle the rest of the the name. @@ -2242,13 +2590,13 @@ namespace Mono.CSharp { Namespace ns = resolved as Namespace; element = elements [i++]; lookup_name += "." + element; - resolved = ns.Lookup (ec.DeclSpace, element, Location.Null); + resolved = ns.Lookup (ec.DeclContainer, element, Location.Null); } if (resolved != null && resolved is TypeExpr) { Type t = ((TypeExpr) resolved).Type; while (t != null) { - if (!ec.DeclSpace.CheckAccessLevel (t)) { + if (!ec.DeclContainer.CheckAccessLevel (t)) { resolved = null; lookup_name = t.FullName; break; @@ -2268,11 +2616,11 @@ namespace Mono.CSharp { } if (!(resolved is TypeExpr)) { - resolved.Error_UnexpectedKind (ec, "type", loc); + resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc); return null; } - type = ((TypeExpr) resolved).ResolveType (ec); + type = resolved.Type; return this; } @@ -2285,32 +2633,103 @@ namespace Mono.CSharp { } } + /// + /// Represents an "unbound generic type", ie. typeof (Foo<>). + /// See 14.5.11. + /// + public class UnboundTypeExpression : TypeExpr + { + MemberName name; + + public UnboundTypeExpression (MemberName name, Location l) + { + this.name = name; + loc = l; + } + + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) + { + Expression expr; + if (name.Left != null) { + Expression lexpr = name.Left.GetTypeExpression (); + expr = new MemberAccess (lexpr, name.Basename); + } else { + expr = new SimpleName (name.Basename, loc); + } + + FullNamedExpression fne = expr.ResolveAsTypeStep (ec, false); + if (fne == null) + return null; + + type = fne.Type; + return new TypeExpression (type, loc); + } + + public override string Name { + get { return name.FullName; } + } + + public override string FullName { + get { return name.FullName; } + } + } + public class TypeAliasExpression : TypeExpr { + FullNamedExpression alias; TypeExpr texpr; + TypeArguments args; + string name; - public TypeAliasExpression (TypeExpr texpr, Location l) + public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l) { - this.texpr = texpr; - loc = texpr.Location; + this.alias = alias; + this.args = args; + loc = l; eclass = ExprClass.Type; + if (args != null) + name = alias.FullName + "<" + args.ToString () + ">"; + else + name = alias.FullName; } public override string Name { - get { return texpr.Name; } + get { return alias.FullName; } } public override string FullName { - get { return texpr.FullName; } + get { return name; } } - public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec) { - Type type = texpr.ResolveType (ec); - if (type == null) + texpr = alias.ResolveAsTypeTerminal (ec, false); + if (texpr == null) return null; - return new TypeExpression (type, loc); + Type type = texpr.Type; + int num_args = TypeManager.GetNumberOfTypeArguments (type); + + if (args != null) { + if (num_args == 0) { + Report.Error (308, loc, + "The non-generic type `{0}' cannot " + + "be used with type arguments.", + TypeManager.CSharpName (type)); + return null; + } + + ConstructedType ctype = new ConstructedType (type, args, loc); + return ctype.ResolveAsTypeTerminal (ec, false); + } else if (num_args > 0) { + Report.Error (305, loc, + "Using the generic type `{0}' " + + "requires {1} type arguments", + TypeManager.CSharpName (type), num_args.ToString ()); + return null; + } + + return texpr; } public override bool CheckAccessLevel (DeclSpace ds) @@ -2386,25 +2805,6 @@ namespace Mono.CSharp { "with an instance reference, qualify it with a type name instead", name); } - protected bool CheckIntermediateModification () - { - if (!InstanceExpression.Type.IsValueType) - return true; - - if (InstanceExpression is UnboxCast) { - Report.Error (445, loc, "Cannot modify the result of an unboxing conversion"); - return false; - } - - if (!(InstanceExpression is IMemoryLocation)) { - Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", - InstanceExpression.GetSignatureForError ()); - return false; - } - - return true; - } - // TODO: possible optimalization // Cache resolved constant result in FieldBuilder <-> expression map public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc, @@ -2417,7 +2817,7 @@ namespace Mono.CSharp { if (left is TypeExpr) { if (!IsStatic) { - SimpleName.Error_ObjectRefRequired (ec, loc, Name); + SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; } @@ -2443,7 +2843,7 @@ namespace Mono.CSharp { return; if (InstanceExpression == EmptyExpression.Null) { - SimpleName.Error_ObjectRefRequired (ec, loc, Name); + SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return; } @@ -2451,7 +2851,7 @@ namespace Mono.CSharp { if (InstanceExpression is IMemoryLocation) { ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore); } else { - LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type); + LocalTemporary t = new LocalTemporary (InstanceExpression.Type); InstanceExpression.Emit (ec); t.Store (ec); t.AddressOf (ec, AddressOp.Store); @@ -2471,7 +2871,8 @@ namespace Mono.CSharp { /// public class MethodGroupExpr : MemberExpr { public MethodBase [] Methods; - bool identical_type_name = false; + bool has_type_arguments = false; + bool identical_type_name = false; bool is_base; public MethodGroupExpr (MemberInfo [] mi, Location l) @@ -2507,10 +2908,20 @@ namespace Mono.CSharp { public override Type DeclaringType { get { // - // The methods are arranged in this order: - // derived type -> base type + // We assume that the top-level type is in the end // - return Methods [0].DeclaringType; + return Methods [Methods.Length - 1].DeclaringType; + //return Methods [0].DeclaringType; + } + } + + public bool HasTypeArguments { + get { + return has_type_arguments; + } + + set { + has_type_arguments = value; } } @@ -2523,7 +2934,7 @@ namespace Mono.CSharp { identical_type_name = value; } } - + public bool IsBase { get { return is_base; @@ -2634,6 +3045,60 @@ namespace Mono.CSharp { { return RemoveMethods (false); } + + public Expression ResolveGeneric (EmitContext ec, TypeArguments args) + { +#if GMCS_SOURCE + if (args.Resolve (ec) == false) + return null; + + Type[] atypes = args.Arguments; + + int first_count = 0; + MethodInfo first = null; + + ArrayList list = new ArrayList (); + foreach (MethodBase mb in Methods) { + MethodInfo mi = mb as MethodInfo; + if ((mi == null) || !mi.IsGenericMethod) + continue; + + Type[] gen_params = mi.GetGenericArguments (); + + if (first == null) { + first = mi; + first_count = gen_params.Length; + } + + if (gen_params.Length != atypes.Length) + continue; + + list.Add (mi.MakeGenericMethod (atypes)); + } + + 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; + } + + if (first != null) + Report.Error ( + 305, loc, "Using the generic method `{0}' " + + "requires {1} type arguments", Name, + first_count.ToString ()); + else + Report.Error ( + 308, loc, "The non-generic method `{0}' " + + "cannot be used with type arguments", Name); + + return null; +#else + throw new NotImplementedException (); +#endif + } } /// @@ -2642,7 +3107,7 @@ namespace Mono.CSharp { public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable { public readonly FieldInfo FieldInfo; VariableInfo variable_info; - + LocalTemporary temp; bool prepared; bool in_initializer; @@ -2657,7 +3122,7 @@ namespace Mono.CSharp { { FieldInfo = fi; eclass = ExprClass.Variable; - type = fi.FieldType; + type = TypeManager.TypeToCoreType (fi.FieldType); loc = l; } @@ -2699,20 +3164,22 @@ namespace Mono.CSharp { public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc, SimpleName original) { - Type t = FieldInfo.FieldType; + FieldInfo fi = TypeManager.GetGenericFieldDefinition (FieldInfo); + + Type t = fi.FieldType; - if (FieldInfo.IsLiteral || (FieldInfo.IsInitOnly && t == TypeManager.decimal_type)) { - IConstant ic = TypeManager.GetConstant (FieldInfo); + if (fi.IsLiteral || (fi.IsInitOnly && t == TypeManager.decimal_type)) { + IConstant ic = TypeManager.GetConstant (fi); if (ic == null) { - if (FieldInfo.IsLiteral) { - ic = new ExternalConstant (FieldInfo); + if (fi.IsLiteral) { + ic = new ExternalConstant (fi); } else { - ic = ExternalConstant.CreateDecimal (FieldInfo); + ic = ExternalConstant.CreateDecimal (fi); if (ic == null) { return base.ResolveMemberAccess (ec, left, loc, original); } } - TypeManager.RegisterConstant (FieldInfo, ic); + TypeManager.RegisterConstant (fi, ic); } bool left_is_type = left is TypeExpr; @@ -2723,7 +3190,7 @@ namespace Mono.CSharp { } if (ic.ResolveValue ()) { - if (ec.TestObsoleteMethodUsage) + if (!ec.IsInObsoleteScope) ic.CheckObsoleteness (loc); } @@ -2740,49 +3207,47 @@ namespace Mono.CSharp { override public Expression DoResolve (EmitContext ec) { - if (ec.InRefOutArgumentResolving && FieldInfo.IsInitOnly && !ec.IsConstructor && FieldInfo.FieldType.IsValueType) { - if (FieldInfo.FieldType is TypeBuilder) { - if (FieldInfo.IsStatic) - Report.Error (1651, loc, "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)", - GetSignatureForError ()); - else - Report.Error (1649, loc, "Members of readonly field `{0}.{1}' cannot be passed ref or out (except in a constructor)", - TypeManager.CSharpName (DeclaringType), Name); - } else { - if (FieldInfo.IsStatic) - Report.Error (199, loc, "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)", - Name); - else - Report.Error (192, loc, "A readonly field `{0}' cannot be passed ref or out (except in a constructor)", - Name); - } - return null; - } + return DoResolve (ec, false, false); + } + Expression DoResolve (EmitContext 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, FieldInfo.Name); + SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return null; } // 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. - InstanceExpression = InstanceExpression.Resolve ( - ec, ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis); + + if (lvalue_instance) { + using (ec.With (EmitContext.Flags.DoFlowAnalysis, false)) { + Expression right_side = + out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; + InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side, loc); + } + } else { + ResolveFlags rf = ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis; + InstanceExpression = InstanceExpression.Resolve (ec, rf); + } + if (InstanceExpression == null) return null; + + InstanceExpression.CheckMarshalByRefAccess (); } if (!in_initializer && !ec.IsFieldInitializer) { ObsoleteAttribute oa; FieldBase f = TypeManager.GetField (FieldInfo); if (f != null) { - if (ec.TestObsoleteMethodUsage) + if (!ec.IsInObsoleteScope) f.CheckObsoleteness (loc); // To be sure that type is external because we do not register generated fields @@ -2802,8 +3267,6 @@ namespace Mono.CSharp { "this"); return null; } - if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This)) - ec.CaptureField (this); } } @@ -2820,16 +3283,41 @@ namespace Mono.CSharp { return this; } - void Report_AssignToReadonly (bool is_instance) - { - string msg; - - if (is_instance) - msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)"; - else - msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)"; + static readonly int [] codes = { + 191, // instance, write access + 192, // instance, out access + 198, // static, write access + 199, // static, out access + 1648, // member of value instance, write access + 1649, // member of value instance, out access + 1650, // member of value static, write access + 1651 // member of value static, out access + }; + + static readonly string [] msgs = { + /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)", + /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)", + /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)", + /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)", + /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)", + /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)", + /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)", + /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)" + }; + + // The return value is always null. Returning a value simplifies calling code. + Expression Report_AssignToReadonly (Expression right_side) + { + int i = 0; + if (right_side == EmptyExpression.OutAccess || 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 ()); - Report.Error (is_instance ? 191 : 198, loc, msg); + return null; } override public Expression DoResolveLValue (EmitContext ec, Expression right_side) @@ -2838,44 +3326,57 @@ namespace Mono.CSharp { if ((var != null) && (var.VariableInfo != null)) var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name); - Expression e = DoResolve (ec); + bool lvalue_instance = !FieldInfo.IsStatic && FieldInfo.DeclaringType.IsValueType; + bool out_access = right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess; - if (e == null) - return null; + Expression e = DoResolve (ec, lvalue_instance, out_access); - if (!FieldInfo.IsStatic && !CheckIntermediateModification ()) + if (e == null) return null; FieldBase fb = TypeManager.GetField (FieldInfo); if (fb != null) fb.SetAssigned (); - if (!FieldInfo.IsInitOnly) - return this; - - // - // InitOnly fields can only be assigned in constructors - // - - if (ec.IsConstructor){ - if (IsStatic && !ec.IsStatic) - Report_AssignToReadonly (false); + if (FieldInfo.IsInitOnly) { + // InitOnly fields can only be assigned in constructors or initializers + if (!ec.IsFieldInitializer && !ec.IsConstructor) + return Report_AssignToReadonly (right_side); + + if (ec.IsConstructor) { + Type ctype = ec.TypeContainer.CurrentType; + if (ctype == null) + ctype = ec.ContainerType; + + // 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); + // static InitOnly fields cannot be assigned-to in an instance constructor + if (IsStatic && !ec.IsStatic) + return Report_AssignToReadonly (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); + } + } - if (ec.ContainerType == FieldInfo.DeclaringType) - return this; + if (right_side == EmptyExpression.OutAccess && + !IsStatic && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) { + Report.SymbolRelatedToPreviousError (DeclaringType); + 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 ()); } - Report_AssignToReadonly (!IsStatic); - - return null; + return this; } - public override void CheckMarshallByRefAccess (Type container) + public override void CheckMarshalByRefAccess () { - if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) { + if (!IsStatic && Type.IsValueType && !(InstanceExpression is This) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) { Report.SymbolRelatedToPreviousError (DeclaringType); - Report.Error (1690, loc, "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", - GetSignatureForError ()); + 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 ()); } } @@ -2888,7 +3389,7 @@ namespace Mono.CSharp { return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed (); } - public override int GetHashCode() + public override int GetHashCode () { return FieldInfo.GetHashCode (); } @@ -2913,15 +3414,13 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; bool is_volatile = false; - if (FieldInfo is FieldBuilder){ - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null){ - if ((f.ModFlags & Modifiers.VOLATILE) != 0) - is_volatile = true; - - f.SetMemberIsUsed (); - } - } + FieldBase f = TypeManager.GetField (FieldInfo); + if (f != null){ + if ((f.ModFlags & Modifiers.VOLATILE) != 0) + is_volatile = true; + + f.SetMemberIsUsed (); + } if (FieldInfo.IsStatic){ if (is_volatile) @@ -2931,7 +3430,7 @@ namespace Mono.CSharp { } else { if (!prepared) EmitInstance (ec, false); - + if (is_volatile) ig.Emit (OpCodes.Volatile); @@ -2946,15 +3445,15 @@ namespace Mono.CSharp { } } - if (leave_copy) { + if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!FieldInfo.IsStatic) { - temp = new LocalTemporary (ec, this.Type); + temp = new LocalTemporary (this.Type); temp.Store (ec); } } } - + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { FieldAttributes fa = FieldInfo.Attributes; @@ -2964,7 +3463,7 @@ namespace Mono.CSharp { prepared = prepare_for_load; if (is_readonly && !ec.IsConstructor){ - Report_AssignToReadonly (!is_static); + Report_AssignToReadonly (source); return; } @@ -2974,28 +3473,28 @@ namespace Mono.CSharp { if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!FieldInfo.IsStatic) { - temp = new LocalTemporary (ec, this.Type); + temp = new LocalTemporary (this.Type); temp.Store (ec); } } - if (FieldInfo is FieldBuilder){ - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null){ - if ((f.ModFlags & Modifiers.VOLATILE) != 0) - ig.Emit (OpCodes.Volatile); + FieldBase f = TypeManager.GetField (FieldInfo); + if (f != null){ + if ((f.ModFlags & Modifiers.VOLATILE) != 0) + ig.Emit (OpCodes.Volatile); - f.SetAssigned (); - } - } + f.SetAssigned (); + } if (is_static) ig.Emit (OpCodes.Stsfld, FieldInfo); else ig.Emit (OpCodes.Stfld, FieldInfo); - if (temp != null) + if (temp != null) { temp.Emit (ec); + temp.Release (ec); + } } public override void Emit (EmitContext ec) @@ -3006,22 +3505,20 @@ namespace Mono.CSharp { public void AddressOf (EmitContext ec, AddressOp mode) { ILGenerator ig = ec.ig; - - if (FieldInfo is FieldBuilder){ - 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", + + 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", f.GetSignatureForError ()); - return; - } - - if ((mode & AddressOp.Store) != 0) - f.SetAssigned (); - if ((mode & AddressOp.Load) != 0) - f.SetMemberIsUsed (); + return; } - } + + if ((mode & AddressOp.Store) != 0) + f.SetAssigned (); + if ((mode & AddressOp.Load) != 0) + f.SetMemberIsUsed (); + } // // Handle initonly fields specially: make a copy and then @@ -3053,7 +3550,8 @@ namespace Mono.CSharp { if (FieldInfo.IsStatic){ ig.Emit (OpCodes.Ldsflda, FieldInfo); } else { - EmitInstance (ec, false); + if (!prepared) + EmitInstance (ec, false); ig.Emit (OpCodes.Ldflda, FieldInfo); } } @@ -3097,7 +3595,7 @@ namespace Mono.CSharp { internal static PtrHashtable AccessorTable = new PtrHashtable (); - public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l) + public PropertyExpr (Type containerType, PropertyInfo pi, Location l) { PropertyInfo = pi; eclass = ExprClass.PropertyAccess; @@ -3106,7 +3604,7 @@ namespace Mono.CSharp { type = TypeManager.TypeToCoreType (pi.PropertyType); - ResolveAccessors (ec); + ResolveAccessors (containerType); } public override string Name { @@ -3140,7 +3638,7 @@ namespace Mono.CSharp { void FindAccessors (Type invocation_type) { - BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | + const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly; @@ -3176,12 +3674,14 @@ namespace Mono.CSharp { // We also perform the permission checking here, as the PropertyInfo does not // hold the information for the accessibility of its setter/getter // - void ResolveAccessors (EmitContext ec) + // TODO: can use TypeManager.GetProperty to boost performance + void ResolveAccessors (Type containerType) { - FindAccessors (ec.ContainerType); + FindAccessors (containerType); if (getter != null) { - IMethodData md = TypeManager.GetMethod (getter); + MethodBase the_getter = TypeManager.DropGenericMethodArguments (getter); + IMethodData md = TypeManager.GetMethod (the_getter); if (md != null) md.SetMemberIsUsed (); @@ -3190,7 +3690,8 @@ namespace Mono.CSharp { } if (setter != null) { - IMethodData md = TypeManager.GetMethod (setter); + MethodBase the_setter = TypeManager.DropGenericMethodArguments (setter); + IMethodData md = TypeManager.GetMethod (the_setter); if (md != null) md.SetMemberIsUsed (); @@ -3199,7 +3700,7 @@ namespace Mono.CSharp { } } - bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check) + bool InstanceResolve (EmitContext ec, bool lvalue_instance, bool must_do_cs1540_check) { if (is_static) { InstanceExpression = null; @@ -3207,22 +3708,26 @@ namespace Mono.CSharp { } if (InstanceExpression == null) { - SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name); + SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return false; } InstanceExpression = InstanceExpression.DoResolve (ec); + if (lvalue_instance && InstanceExpression != null) + InstanceExpression = InstanceExpression.ResolveLValue (ec, EmptyExpression.LValueMemberAccess, loc); + if (InstanceExpression == null) return false; - - InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); - if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null && - InstanceExpression.Type != ec.ContainerType && - ec.ContainerType.IsSubclassOf (PropertyInfo.DeclaringType) && - InstanceExpression.Type.IsSubclassOf (PropertyInfo.DeclaringType)) { - Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType); - return false; + InstanceExpression.CheckMarshalByRefAccess (); + + if (must_do_cs1540_check && (InstanceExpression != EmptyExpression.Null) && + !TypeManager.IsInstantiationOfSameGenericType (InstanceExpression.Type, ec.ContainerType) && + !TypeManager.IsNestedChildOf (ec.ContainerType, InstanceExpression.Type) && + !TypeManager.IsSubclassOf (InstanceExpression.Type, ec.ContainerType)) { + Report.SymbolRelatedToPreviousError (PropertyInfo); + Error_CannotAccessProtected (loc, PropertyInfo, InstanceExpression.Type, ec.ContainerType); + return false; } return true; @@ -3286,12 +3791,14 @@ namespace Mono.CSharp { 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 + else { + Report.SymbolRelatedToPreviousError (getter); ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter)); + } return null; } - if (!InstanceResolve (ec, must_do_cs1540_check)) + if (!InstanceResolve (ec, false, must_do_cs1540_check)) return null; // @@ -3314,6 +3821,18 @@ 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", + GetSignatureForError ()); + return null; + } + + if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) { + Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", + GetSignatureForError ()); + return null; + } + if (setter == null){ // // The following condition happens if the PropertyExpr was @@ -3323,9 +3842,8 @@ namespace Mono.CSharp { // if (getter == null) return null; - - Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)", - TypeManager.GetFullNameSignature (PropertyInfo)); + Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read only)", + GetSignatureForError ()); return null; } @@ -3342,12 +3860,14 @@ namespace Mono.CSharp { 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 + else { + Report.SymbolRelatedToPreviousError (setter); ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter)); + } return null; } - if (!InstanceResolve (ec, must_do_cs1540_check)) + if (!InstanceResolve (ec, PropertyInfo.DeclaringType.IsValueType, must_do_cs1540_check)) return null; // @@ -3358,12 +3878,6 @@ namespace Mono.CSharp { return null; } - // - // Check that we are not making changes to a temporary memory location - // - if (InstanceExpression != null && !CheckIntermediateModification ()) - return null; - return this; } @@ -3399,7 +3913,7 @@ namespace Mono.CSharp { if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!is_static) { - temp = new LocalTemporary (ec, this.Type); + temp = new LocalTemporary (this.Type); temp.Store (ec); } } @@ -3419,14 +3933,14 @@ namespace Mono.CSharp { if (leave_copy) { ec.ig.Emit (OpCodes.Dup); if (!is_static) { - temp = new LocalTemporary (ec, this.Type); + temp = new LocalTemporary (this.Type); temp.Store (ec); } } } else if (leave_copy) { source.Emit (ec); if (!is_static) { - temp = new LocalTemporary (ec, this.Type); + temp = new LocalTemporary (this.Type); temp.Store (ec); } my_source = temp; @@ -3437,8 +3951,10 @@ namespace Mono.CSharp { Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared); - if (temp != null) + if (temp != null) { temp.Emit (ec); + temp.Release (ec); + } } } @@ -3450,6 +3966,8 @@ namespace Mono.CSharp { bool is_static; MethodInfo add_accessor, remove_accessor; + + internal static PtrHashtable AccessorTable = new PtrHashtable (); public EventExpr (EventInfo ei, Location loc) { @@ -3459,6 +3977,10 @@ namespace Mono.CSharp { add_accessor = TypeManager.GetAddMethod (ei); remove_accessor = TypeManager.GetRemoveMethod (ei); + if (add_accessor != null) + AccessorTable [add_accessor] = ei; + if (remove_accessor != null) + AccessorTable [remove_accessor] = ei; if (add_accessor.IsStatic || remove_accessor.IsStatic) is_static = true; @@ -3507,7 +4029,7 @@ namespace Mono.CSharp { MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo); if (mi != null) { - MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc); + MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec.ContainerType, mi, loc); if (ml == null) { Report.Error (-200, loc, "Internal error!!"); @@ -3532,7 +4054,7 @@ namespace Mono.CSharp { } if (InstanceExpression == null) { - SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name); + SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ()); return false; } @@ -3544,12 +4066,12 @@ namespace Mono.CSharp { // This is using the same mechanism as the CS1540 check in PropertyExpr. // However, in the Event case, we reported a CS0122 instead. // - if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) { - if ((InstanceExpression.Type != ec.ContainerType) && - ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) { - ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); - return false; - } + if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null && + InstanceExpression.Type != ec.ContainerType && + ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) { + Report.SymbolRelatedToPreviousError (EventInfo); + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); + return false; } return true; @@ -3565,6 +4087,7 @@ namespace Mono.CSharp { bool must_do_cs1540_check; if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) && IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) { + Report.SymbolRelatedToPreviousError (EventInfo); ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); return null; } @@ -3608,10 +4131,10 @@ namespace Mono.CSharp { } } - public class TemporaryVariable : Expression, IMemoryLocation { LocalInfo li; + Variable var; public TemporaryVariable (Type type, Location loc) { @@ -3629,64 +4152,47 @@ namespace Mono.CSharp { li = ec.CurrentBlock.AddTemporaryVariable (te, loc); if (!li.Resolve (ec)) return null; - - AnonymousContainer am = ec.CurrentAnonymousMethod; - if ((am != null) && am.IsIterator) - ec.CaptureVariable (li); + + if (ec.MustCaptureVariable (li)) { + ScopeInfo scope = li.Block.CreateScopeInfo (); + var = scope.AddLocal (li); + type = var.Type; + } return this; } + + public Variable Variable { + get { return var != null ? var : li.Variable; } + } public override void Emit (EmitContext ec) { - ILGenerator ig = ec.ig; - - if (li.FieldBuilder != null) { - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldfld, li.FieldBuilder); - } else { - ig.Emit (OpCodes.Ldloc, li.LocalBuilder); - } + Variable.EmitInstance (ec); + Variable.Emit (ec); } public void EmitLoadAddress (EmitContext ec) { - ILGenerator ig = ec.ig; - - if (li.FieldBuilder != null) { - ig.Emit (OpCodes.Ldarg_0); - ig.Emit (OpCodes.Ldflda, li.FieldBuilder); - } else { - ig.Emit (OpCodes.Ldloca, li.LocalBuilder); - } + Variable.EmitInstance (ec); + Variable.EmitAddressOf (ec); } public void Store (EmitContext ec, Expression right_side) { - if (li.FieldBuilder != null) - ec.ig.Emit (OpCodes.Ldarg_0); - + Variable.EmitInstance (ec); right_side.Emit (ec); - if (li.FieldBuilder != null) { - ec.ig.Emit (OpCodes.Stfld, li.FieldBuilder); - } else { - ec.ig.Emit (OpCodes.Stloc, li.LocalBuilder); - } + Variable.EmitAssign (ec); } public void EmitThis (EmitContext ec) { - if (li.FieldBuilder != null) { - ec.ig.Emit (OpCodes.Ldarg_0); - } + Variable.EmitInstance (ec); } - public void EmitStore (ILGenerator ig) + public void EmitStore (EmitContext ec) { - if (li.FieldBuilder != null) - ig.Emit (OpCodes.Stfld, li.FieldBuilder); - else - ig.Emit (OpCodes.Stloc, li.LocalBuilder); + Variable.EmitAssign (ec); } public void AddressOf (EmitContext ec, AddressOp mode)