X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fecore.cs;h=3d4786437d3a1dc56537c96eb66eb7a1f6286b47;hb=bd316288ae3fa0cb6f03b367716d04d5244c5d04;hp=2ddfafd98e70d159c320faa4c34da2e9cebfe6dd;hpb=7ada3771f69aa64bcf28e01914a9f1284f74bb86;p=mono.git diff --git a/mcs/gmcs/ecore.cs b/mcs/gmcs/ecore.cs index 2ddfafd98e7..3d4786437d3 100644 --- a/mcs/gmcs/ecore.cs +++ b/mcs/gmcs/ecore.cs @@ -51,20 +51,20 @@ namespace Mono.CSharp { // Returns a method group. MethodGroup = 4, - // Allows SimpleNames to be returned. - // This is used by MemberAccess to construct long names that can not be - // partially resolved (namespace-qualified names for example). - SimpleName = 8, - // Mask of all the expression class flags. - MaskExprClass = 15, + MaskExprClass = 7, // Disable control flow analysis while resolving the expression. // This is used when resolving the instance expression of a field expression. - DisableFlowAnalysis = 16, + DisableFlowAnalysis = 8, // Set if this is resolving the first part of a MemberAccess. - Intermediate = 32 + Intermediate = 16, + + // Disable control flow analysis _of struct_ while resolving the expression. + // This is used when resolving the instance expression of a field expression. + DisableStructFlowAnalysis = 32, + } // @@ -95,23 +95,6 @@ namespace Mono.CSharp { void AddressOf (EmitContext ec, AddressOp mode); } - /// - /// We are either a namespace or a type. - /// If we're a type, `IsType' is true and we may use `Type' to get - /// a TypeExpr representing that type. - /// - public interface IAlias { - bool IsType { - get; - } - - string Name { - get; - } - - TypeExpr ResolveAsType (EmitContext ec); - } - /// /// This interface is implemented by variables /// @@ -120,50 +103,7 @@ namespace Mono.CSharp { get; } - bool VerifyFixed (bool is_expression); - } - - /// - /// This interface denotes an expression which evaluates to a member - /// of a struct or a class. - /// - public interface IMemberExpr - { - /// - /// The name of this member. - /// - string Name { - get; - } - - /// - /// Whether this is an instance member. - /// - bool IsInstance { - get; - } - - /// - /// Whether this is a static member. - /// - bool IsStatic { - get; - } - - /// - /// The type which declares this member. - /// - Type DeclaringType { - get; - } - - /// - /// The instance expression associated with this member, if it's a - /// non-static member. - /// - Expression InstanceExpression { - get; set; - } + bool VerifyFixed (); } /// @@ -175,19 +115,12 @@ namespace Mono.CSharp { protected Location loc; public Type Type { - get { - return type; - } - - set { - type = value; - } + get { return type; } + set { type = value; } } public Location Location { - get { - return loc; - } + get { return loc; } } /// @@ -195,10 +128,10 @@ namespace Mono.CSharp { /// public void Error (int error, string s) { - if (!Location.IsNull (loc)) - Report.Error (error, loc, s); - else + if (loc.IsNull) Report.Error (error, s); + else + Report.Error (error, loc, s); } /// @@ -224,6 +157,11 @@ namespace Mono.CSharp { AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc); } + public virtual string GetSignatureForError () + { + return TypeManager.CSharpName (type); + } + public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check) { MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask; @@ -233,34 +171,23 @@ namespace Mono.CSharp { // // If only accessible to the current class or children // - if (ma == MethodAttributes.Private) { - Type declaring_type = mi.DeclaringType; - - if (invocation_type != declaring_type) - return TypeManager.IsNestedFamilyAccessible (invocation_type, declaring_type); - - return true; - } - // - // FamAndAssem requires that we not only derivate, but we are on the - // same assembly. - // - if (ma == MethodAttributes.FamANDAssem){ - return (mi.DeclaringType.Assembly != invocation_type.Assembly); - } + if (ma == MethodAttributes.Private) + return TypeManager.IsPrivateAccessible (invocation_type, mi.DeclaringType) || + TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType); - // Assembly and FamORAssem succeed if we're in the same assembly. - if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){ - if (mi.DeclaringType.Assembly == invocation_type.Assembly) + if (mi.DeclaringType.Assembly == invocation_type.Assembly) { + if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem) return true; + } else { + if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem) + return false; } - // We already know that we aren't in the same assembly. - if (ma == MethodAttributes.Assembly) - return false; - // Family and FamANDAssem require that we derive. - if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){ + // 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; @@ -304,15 +231,19 @@ namespace Mono.CSharp { public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side) { - return DoResolve (ec); + return null; } // - // This is used if the expression should be resolved as a type. - // the default implementation fails. Use this method in - // those participants in the SimpleName chain system. + // This is used if the expression should be resolved as a type or namespace name. + // the default implementation fails. // - public virtual Expression ResolveAsTypeStep (EmitContext ec) + public FullNamedExpression ResolveAsTypeStep (EmitContext ec) + { + return ResolveAsTypeStep (ec, false); + } + + public virtual FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) { return null; } @@ -322,25 +253,79 @@ namespace Mono.CSharp { // value will be returned if the expression is not a type // reference // - public virtual TypeExpr ResolveAsTypeTerminal (EmitContext ec) + public TypeExpr ResolveAsTypeTerminal (EmitContext ec) + { + return ResolveAsTypeTerminal (ec, false); + } + + public virtual TypeExpr ResolveAsTypeTerminal (EmitContext ec, bool silent) { int errors = Report.Errors; - TypeExpr te = ResolveAsTypeStep (ec) as TypeExpr; + FullNamedExpression fne = ResolveAsTypeStep (ec, silent); - if ((te == null) || (te.eclass != ExprClass.Type) || (te.Type == null)) { - if (errors == Report.Errors) - Report.Error (246, Location, "Cannot find type '{0}'", ToString ()); + if (fne == null) + return null; + + if (fne.eclass != ExprClass.Type) { + if (!silent && (errors == Report.Errors)) + fne.Error_UnexpectedKind (null, "type", loc); return null; } + TypeExpr te = fne as TypeExpr; + if (!te.CheckAccessLevel (ec.DeclSpace)) { - Report.Error (122, Location, "'{0}' is inaccessible due to its protection level", te.Name); + ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type)); return null; } + ConstructedType ct = te as ConstructedType; + if ((ct != null) && !ec.ResolvingTypeTree && !ct.CheckConstraints (ec)) + return null; + return te; } + + public static void ErrorIsInaccesible (Location loc, string name) + { + Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name); + } + + public virtual void Error_ValueCannotBeConverted (Location loc, Type t) + { + Convert.Error_CannotImplicitConversion (loc, Type, t); + } + + protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name) + { + Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'", + TypeManager.CSharpName (type), name); + } + + ResolveFlags ExprClassToResolveFlags () + { + switch (eclass) { + case ExprClass.Type: + case ExprClass.Namespace: + return ResolveFlags.Type; + + case ExprClass.MethodGroup: + return ResolveFlags.MethodGroup; + + 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"); + } + + } /// /// Resolves an expression and performs semantic analysis on it. @@ -353,89 +338,40 @@ namespace Mono.CSharp { public Expression Resolve (EmitContext ec, ResolveFlags flags) { if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) - return ResolveAsTypeStep (ec); + return ResolveAsTypeStep (ec, false); bool old_do_flow_analysis = ec.DoFlowAnalysis; + bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis; if ((flags & ResolveFlags.DisableFlowAnalysis) != 0) ec.DoFlowAnalysis = false; + if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0) + ec.OmitStructFlowAnalysis = true; Expression e; bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate; if (this is SimpleName) - e = ((SimpleName) this).DoResolveAllowStatic (ec, intermediate); + e = ((SimpleName) this).DoResolve (ec, intermediate); else e = DoResolve (ec); ec.DoFlowAnalysis = old_do_flow_analysis; + ec.OmitStructFlowAnalysis = old_omit_struct_analysis; if (e == null) return null; - if (e is SimpleName){ - SimpleName s = (SimpleName) e; - - if ((flags & ResolveFlags.SimpleName) == 0) { - MemberLookupFailed (ec, null, ec.ContainerType, s.Name, - ec.DeclSpace.Name, loc); - return null; - } - - return s; - } - - if ((e is TypeExpr) || (e is ComposedCast)) { - if ((flags & ResolveFlags.Type) == 0) { - e.Error_UnexpectedKind (flags, loc); - return null; - } - - return e; - } - - switch (e.eclass) { - case ExprClass.Type: - if ((flags & ResolveFlags.VariableOrValue) == 0) { - e.Error_UnexpectedKind (flags, loc); - return null; - } - break; - - case ExprClass.MethodGroup: - if (RootContext.Version == LanguageVersion.ISO_1){ - if ((flags & ResolveFlags.MethodGroup) == 0) { - ((MethodGroupExpr) e).ReportUsageError (); - return null; - } - } - break; - - case ExprClass.Value: - case ExprClass.Variable: - case ExprClass.PropertyAccess: - case ExprClass.EventAccess: - case ExprClass.IndexerAccess: - if ((flags & ResolveFlags.VariableOrValue) == 0) { - Console.WriteLine ("I got: {0} and {1}", e.GetType (), e); - Console.WriteLine ("I am {0} and {1}", this.GetType (), this); - FieldInfo fi = ((FieldExpr) e).FieldInfo; - - Console.WriteLine ("{0} and {1}", fi.DeclaringType, fi.Name); - e.Error_UnexpectedKind (flags, loc); - return null; - } - break; - - default: - throw new Exception ("Expression " + e.GetType () + - " ExprClass is Invalid after resolve"); + if ((flags & e.ExprClassToResolveFlags ()) == 0) { + e.Error_UnexpectedKind (flags, loc); + return null; } - if (e.type == null) + if (e.type == null && !(e is Namespace)) { throw new Exception ( "Expression " + e.GetType () + " did not set its type after Resolve\n" + "called from: " + this.GetType ()); + } return e; } @@ -445,7 +381,38 @@ namespace Mono.CSharp { /// public Expression Resolve (EmitContext ec) { - return Resolve (ec, ResolveFlags.VariableOrValue); + Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + + if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) { + ((MethodGroupExpr) e).ReportUsageError (); + return null; + } + return e; + } + + public Constant ResolveAsConstant (EmitContext ec, MemberCore mc) + { + Expression e = Resolve (ec); + if (e != null) { + Constant c = e as Constant; + 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; } /// @@ -456,18 +423,18 @@ namespace Mono.CSharp { /// Currently ResolveLValue wraps DoResolveLValue to perform sanity /// checking and assertion checking on what we expect from Resolve /// - public Expression ResolveLValue (EmitContext ec, Expression right_side) + public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc) { + int errors = Report.Errors; Expression e = DoResolveLValue (ec, right_side); - if (e != null){ - if (e is SimpleName){ - SimpleName s = (SimpleName) e; - MemberLookupFailed (ec, null, ec.ContainerType, s.Name, - ec.DeclSpace.Name, loc); - return 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"); + return null; + } + if (e != null){ if (e.eclass == ExprClass.Invalid) throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); @@ -573,6 +540,8 @@ namespace Mono.CSharp { /// /// Returns a fully formed expression after a MemberLookup /// + /// + // TODO: This can be heavily cached public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc) { if (mi is EventInfo) @@ -588,8 +557,7 @@ namespace Mono.CSharp { return null; } - - private static ArrayList almostMatchedMembers = new ArrayList (4); + protected static ArrayList almostMatchedMembers = new ArrayList (4); // // FIXME: Probably implement a cache for (t,name,current_access_set)? @@ -638,7 +606,7 @@ namespace Mono.CSharp { almostMatchedMembers.Clear (); MemberInfo [] mi = TypeManager.MemberLookup ( - container_type, qualifier_type,queried_type, mt, bf, name, + container_type, qualifier_type, queried_type, mt, bf, name, almostMatchedMembers); if (mi == null) @@ -678,8 +646,14 @@ namespace Mono.CSharp { public static Expression MemberLookup (EmitContext ec, Type qualifier_type, Type queried_type, string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, - name, AllMemberTypes, AllBindingFlags, loc); + if (ec.ResolvingTypeTree) + return MemberLookup (ec, ec.ContainerType, qualifier_type, + queried_type, name, MemberTypes.NestedType, + AllBindingFlags, loc); + else + return MemberLookup (ec, ec.ContainerType, qualifier_type, + queried_type, name, AllMemberTypes, + AllBindingFlags, loc); } public static Expression MethodLookup (EmitContext ec, Type queried_type, @@ -717,65 +691,77 @@ namespace Mono.CSharp { 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, loc); + MemberLookupFailed (ec, qualifier_type, queried_type, name, null, true, loc); return e; } public static void MemberLookupFailed (EmitContext ec, Type qualifier_type, Type queried_type, string name, - string class_name, Location loc) + string class_name, bool complain_if_none_found, + Location loc) { if (almostMatchedMembers.Count != 0) { - if (qualifier_type == null) { - foreach (MemberInfo m in almostMatchedMembers) - Report.Error (38, loc, - "Cannot access non-static member `{0}' via nested type `{1}'", - TypeManager.GetFullNameSignature (m), + for (int i = 0; i < almostMatchedMembers.Count; ++i) { + MemberInfo m = (MemberInfo) almostMatchedMembers [i]; + for (int j = 0; j < i; ++j) { + if (m == almostMatchedMembers [j]) { + m = null; + break; + } + } + if (m == null) + continue; + + Type declaring_type = m.DeclaringType; + + Report.SymbolRelatedToPreviousError (m); + 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)); - return; - } - - - if (qualifier_type != ec.ContainerType) { - // 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. - foreach (MemberInfo m in almostMatchedMembers) + } else if (qualifier_type != ec.ContainerType && + TypeManager.IsNestedFamilyAccessible (ec.ContainerType, 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. 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_type), TypeManager.CSharpName (ec.ContainerType)); - return; + } else { + ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (m)); + } } almostMatchedMembers.Clear (); + return; } - MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type, - AllMemberTypes, AllBindingFlags | - BindingFlags.NonPublic, name, null); + MemberInfo[] lookup = TypeManager.MemberLookup (queried_type, null, queried_type, + AllMemberTypes, AllBindingFlags | + BindingFlags.NonPublic, name, null); + + if (lookup == null) { + if (!complain_if_none_found) + return; - if (mi == null) { if (class_name != null) - Report.Error (103, loc, "The name `" + name + "' could not be " + - "found in `" + class_name + "'"); + Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'", + name, class_name); else - Report.Error ( - 117, loc, "`" + queried_type + "' does not contain a " + - "definition for `" + name + "'"); + Error_TypeDoesNotContainDefinition (loc, queried_type, name); return; } if (TypeManager.MemberLookup (queried_type, null, queried_type, AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic, name, null) == null) { - if ((mi.Length == 1) && (mi [0] is Type)) { - Type t = (Type) mi [0]; + if ((lookup.Length == 1) && (lookup [0] is Type)) { + Type t = (Type) lookup [0]; Report.Error (305, loc, "Using the generic type `{0}' " + @@ -786,32 +772,22 @@ namespace Mono.CSharp { } } - if (name == ".ctor" && TypeManager.FindMembers (qualifier_type, MemberTypes.Constructor, - BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null).Count == 0) + 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, String.Format ("The type '{0}' has no constructors defined", TypeManager.CSharpName (queried_type))); + Report.Error (143, loc, String.Format ("The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type))); return; } - if (qualifier_type != null) { - Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", TypeManager.CSharpName (qualifier_type) + "." + name); - } else { - Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", name); - } + ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0])); } - static public MemberInfo GetFieldFromEvent (EventExpr event_expr) - { - EventInfo ei = event_expr.EventInfo; - - return TypeManager.GetPrivateFieldOfEvent (ei); - } - /// /// 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); } @@ -820,16 +796,19 @@ 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 (TypeManager.IsNullableType (e.Type)) + return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec); + operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc); if (operator_group == null) return null; @@ -858,7 +837,7 @@ namespace Mono.CSharp { if (e.Type == TypeManager.bool_type) return e; - Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, new Location (-1)); + Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null); if (converted != null) return converted; @@ -874,9 +853,9 @@ namespace Mono.CSharp { return operator_true; } - static string ExprClassName (ExprClass c) + string ExprClassName () { - switch (c){ + switch (eclass){ case ExprClass.Invalid: return "Invalid"; case ExprClass.Value: @@ -904,335 +883,57 @@ namespace Mono.CSharp { /// /// Reports that we were expecting `expr' to be of class `expected' /// - public void Error_UnexpectedKind (string expected, Location loc) + public void Error_UnexpectedKind (EmitContext ec, string expected, Location loc) { - string kind = "Unknown"; - - kind = ExprClassName (eclass); + Error_UnexpectedKind (ec, expected, ExprClassName (), loc); + } + + public void Error_UnexpectedKind (EmitContext ec, string expected, string was, Location loc) + { + string name = GetSignatureForError (); + if (ec != null) + name = ec.DeclSpace.GetSignatureForError () + '.' + name; - Report.Error (118, loc, "Expression denotes a `" + kind + - "' where a `" + expected + "' was expected"); + Report.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", + name, was, expected); } public void Error_UnexpectedKind (ResolveFlags flags, Location loc) { - ArrayList valid = new ArrayList (10); + string [] valid = new string [4]; + int count = 0; if ((flags & ResolveFlags.VariableOrValue) != 0) { - valid.Add ("variable"); - valid.Add ("value"); + valid [count++] = "variable"; + valid [count++] = "value"; } if ((flags & ResolveFlags.Type) != 0) - valid.Add ("type"); + valid [count++] = "type"; if ((flags & ResolveFlags.MethodGroup) != 0) - valid.Add ("method group"); - - if ((flags & ResolveFlags.SimpleName) != 0) - valid.Add ("simple name"); + valid [count++] = "method group"; - if (valid.Count == 0) - valid.Add ("unknown"); + if (count == 0) + valid [count++] = "unknown"; - StringBuilder sb = new StringBuilder (); - for (int i = 0; i < valid.Count; i++) { - if (i > 0) - sb.Append (", "); - else if (i == valid.Count) - sb.Append (" or "); + StringBuilder sb = new StringBuilder (valid [0]); + for (int i = 1; i < count - 1; i++) { + sb.Append ("', `"); sb.Append (valid [i]); } + if (count > 1) { + sb.Append ("' or `"); + sb.Append (valid [count - 1]); + } - string kind = ExprClassName (eclass); - - Error (119, "Expression denotes a `" + kind + "' where " + - "a `" + sb.ToString () + "' was expected"); + Report.Error (119, loc, + "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName (), sb); } - static public void Error_ConstantValueCannotBeConverted (Location l, string val, Type t) - { - Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " + - TypeManager.CSharpName (t)); - } - public static void UnsafeError (Location loc) { - Report.Error (214, loc, "Pointers may only be used in an unsafe context"); - } - - /// - /// Converts the IntConstant, UIntConstant, LongConstant or - /// ULongConstant into the integral target_type. Notice - /// that we do not return an `Expression' we do return - /// a boxed integral type. - /// - /// FIXME: Since I added the new constants, we need to - /// also support conversions from CharConstant, ByteConstant, - /// SByteConstant, UShortConstant, ShortConstant - /// - /// This is used by the switch statement, so the domain - /// of work is restricted to the literals above, and the - /// targets are int32, uint32, char, byte, sbyte, ushort, - /// short, uint64 and int64 - /// - public static object ConvertIntLiteral (Constant c, Type target_type, Location loc) - { - if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, c, target_type)){ - Convert.Error_CannotImplicitConversion (loc, c.Type, target_type); - return null; - } - - string s = ""; - - if (c.Type == target_type) - return ((Constant) c).GetValue (); - - // - // Make into one of the literals we handle, we dont really care - // about this value as we will just return a few limited types - // - if (c is EnumConstant) - c = ((EnumConstant)c).WidenToCompilerConstant (); - - if (c is IntConstant){ - int v = ((IntConstant) c).Value; - - if (target_type == TypeManager.uint32_type){ - if (v >= 0) - return (uint) v; - } else if (target_type == TypeManager.char_type){ - if (v >= Char.MinValue && v <= Char.MaxValue) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v >= Byte.MinValue && v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v >= SByte.MinValue && v <= SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.short_type){ - if (v >= Int16.MinValue && v <= UInt16.MaxValue) - return (short) v; - } else if (target_type == TypeManager.ushort_type){ - if (v >= UInt16.MinValue && v <= UInt16.MaxValue) - return (ushort) v; - } else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type){ - if (v > 0) - return (ulong) v; - } - - s = v.ToString (); - } else if (c is UIntConstant){ - uint v = ((UIntConstant) c).Value; - - if (target_type == TypeManager.int32_type){ - if (v <= Int32.MaxValue) - return (int) v; - } else if (target_type == TypeManager.char_type){ - if (v >= Char.MinValue && v <= Char.MaxValue) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v <= SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.short_type){ - if (v <= UInt16.MaxValue) - return (short) v; - } else if (target_type == TypeManager.ushort_type){ - if (v <= UInt16.MaxValue) - return (ushort) v; - } else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type) - return (ulong) v; - s = v.ToString (); - } else if (c is LongConstant){ - long v = ((LongConstant) c).Value; - - if (target_type == TypeManager.int32_type){ - if (v >= UInt32.MinValue && v <= UInt32.MaxValue) - return (int) v; - } else if (target_type == TypeManager.uint32_type){ - if (v >= 0 && v <= UInt32.MaxValue) - return (uint) v; - } else if (target_type == TypeManager.char_type){ - if (v >= Char.MinValue && v <= Char.MaxValue) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v >= Byte.MinValue && v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v >= SByte.MinValue && v <= SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.short_type){ - if (v >= Int16.MinValue && v <= UInt16.MaxValue) - return (short) v; - } else if (target_type == TypeManager.ushort_type){ - if (v >= UInt16.MinValue && v <= UInt16.MaxValue) - return (ushort) v; - } else if (target_type == TypeManager.uint64_type){ - if (v > 0) - return (ulong) v; - } - s = v.ToString (); - } else if (c is ULongConstant){ - ulong v = ((ULongConstant) c).Value; - - if (target_type == TypeManager.int32_type){ - if (v <= Int32.MaxValue) - return (int) v; - } else if (target_type == TypeManager.uint32_type){ - if (v <= UInt32.MaxValue) - return (uint) v; - } else if (target_type == TypeManager.char_type){ - if (v >= Char.MinValue && v <= Char.MaxValue) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v >= Byte.MinValue && v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v <= (int) SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.short_type){ - if (v <= UInt16.MaxValue) - return (short) v; - } else if (target_type == TypeManager.ushort_type){ - if (v <= UInt16.MaxValue) - return (ushort) v; - } else if (target_type == TypeManager.int64_type){ - if (v <= Int64.MaxValue) - return (long) v; - } - s = v.ToString (); - } else if (c is ByteConstant){ - byte v = ((ByteConstant) c).Value; - - if (target_type == TypeManager.int32_type) - return (int) v; - else if (target_type == TypeManager.uint32_type) - return (uint) v; - else if (target_type == TypeManager.char_type) - return (char) v; - else if (target_type == TypeManager.sbyte_type){ - if (v <= SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.short_type) - return (short) v; - else if (target_type == TypeManager.ushort_type) - return (ushort) v; - else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type) - return (ulong) v; - s = v.ToString (); - } else if (c is SByteConstant){ - sbyte v = ((SByteConstant) c).Value; - - if (target_type == TypeManager.int32_type) - return (int) v; - else if (target_type == TypeManager.uint32_type){ - if (v >= 0) - return (uint) v; - } else if (target_type == TypeManager.char_type){ - if (v >= 0) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v >= 0) - return (byte) v; - } else if (target_type == TypeManager.short_type) - return (short) v; - else if (target_type == TypeManager.ushort_type){ - if (v >= 0) - return (ushort) v; - } else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type){ - if (v >= 0) - return (ulong) v; - } - s = v.ToString (); - } else if (c is ShortConstant){ - short v = ((ShortConstant) c).Value; - - if (target_type == TypeManager.int32_type){ - return (int) v; - } else if (target_type == TypeManager.uint32_type){ - if (v >= 0) - return (uint) v; - } else if (target_type == TypeManager.char_type){ - if (v >= 0) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v >= Byte.MinValue && v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v >= SByte.MinValue && v <= SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.ushort_type){ - if (v >= 0) - return (ushort) v; - } else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type) - return (ulong) v; - - s = v.ToString (); - } else if (c is UShortConstant){ - ushort v = ((UShortConstant) c).Value; - - if (target_type == TypeManager.int32_type) - return (int) v; - else if (target_type == TypeManager.uint32_type) - return (uint) v; - else if (target_type == TypeManager.char_type){ - if (v >= Char.MinValue && v <= Char.MaxValue) - return (char) v; - } else if (target_type == TypeManager.byte_type){ - if (v >= Byte.MinValue && v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v <= SByte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.short_type){ - if (v <= Int16.MaxValue) - return (short) v; - } else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type) - return (ulong) v; - - s = v.ToString (); - } else if (c is CharConstant){ - char v = ((CharConstant) c).Value; - - if (target_type == TypeManager.int32_type) - return (int) v; - else if (target_type == TypeManager.uint32_type) - return (uint) v; - else if (target_type == TypeManager.byte_type){ - if (v >= Byte.MinValue && v <= Byte.MaxValue) - return (byte) v; - } else if (target_type == TypeManager.sbyte_type){ - if (v <= SByte.MaxValue) - return (sbyte) v; - } else if (target_type == TypeManager.short_type){ - if (v <= Int16.MaxValue) - return (short) v; - } else if (target_type == TypeManager.ushort_type) - return (short) v; - else if (target_type == TypeManager.int64_type) - return (long) v; - else if (target_type == TypeManager.uint64_type) - return (ulong) v; - - s = v.ToString (); - } - Error_ConstantValueCannotBeConverted (loc, s, target_type); - return null; + Report.Error (214, loc, "Pointers and fixed size buffers may only be used in an unsafe context"); } // @@ -1340,6 +1041,11 @@ namespace Mono.CSharp { { Report.Error (248, loc, "Cannot create an array with a negative size"); } + + protected void Error_CannotCallAbstractBase (string name) + { + Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name); + } // // Converts `source' to an int, uint, long or ulong. @@ -1446,6 +1152,7 @@ namespace Mono.CSharp { public EmptyCast (Expression child, Type return_type) { eclass = child.eclass; + loc = child.Location; type = return_type; this.child = child; } @@ -1463,37 +1170,135 @@ namespace Mono.CSharp { child.Emit (ec); } } + /// + /// This is a numeric cast to a Decimal + /// + public class CastToDecimal : EmptyCast { - // - // We need to special case this since an empty cast of - // a NullLiteral is still a Constant - // - public class NullCast : Constant { - protected Expression child; - - public NullCast (Expression child, Type return_type) - { - eclass = child.eclass; - type = return_type; - this.child = child; - } + MethodInfo conversion_operator; - override public string AsString () + public CastToDecimal (EmitContext ec, Expression child) + : this (ec, child, false) { - return "null"; } - public override object GetValue () + public CastToDecimal (EmitContext ec, Expression child, bool find_explicit) + : base (child, TypeManager.decimal_type) { - return null; + conversion_operator = GetConversionOperator (ec, find_explicit); + + if (conversion_operator == null) + Convert.Error_CannotImplicitConversion (loc, child.Type, type); } - public override Expression DoResolve (EmitContext ec) + // Returns the implicit operator that converts from + // 'child.Type' to System.Decimal. + MethodInfo GetConversionOperator (EmitContext ec, bool find_explicit) { - // This should never be invoked, we are born in fully - // initialized state. + string operator_name = "op_Implicit"; - return this; + if (find_explicit) + operator_name = "op_Explicit"; + + MethodGroupExpr opers = Expression.MethodLookup ( + ec, type, operator_name, loc) as MethodGroupExpr; + + if (opers == null) + Convert.Error_CannotImplicitConversion (loc, child.Type, type); + + foreach (MethodInfo oper in opers.Methods) { + 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); + + ig.Emit (OpCodes.Call, conversion_operator); + } + } + /// + /// This is an explicit numeric cast from a Decimal + /// + public class CastFromDecimal : EmptyCast + { + MethodInfo conversion_operator; + public CastFromDecimal (EmitContext ec, Expression child, Type return_type) + : base (child, return_type) + { + if (child.Type != TypeManager.decimal_type) + throw new InternalErrorException ( + "The expected type is Decimal, instead it is " + child.Type.FullName); + + conversion_operator = GetConversionOperator (ec); + if (conversion_operator == null) + Convert.Error_CannotImplicitConversion (loc, child.Type, type); + } + + // Returns the explicit operator that converts from an + // express of type System.Decimal to 'type'. + MethodInfo GetConversionOperator (EmitContext ec) + { + MethodGroupExpr opers = Expression.MethodLookup ( + ec, child.Type, "op_Explicit", loc) as MethodGroupExpr; + + if (opers == null) + Convert.Error_CannotImplicitConversion (loc, child.Type, type); + + foreach (MethodInfo oper in opers.Methods) { + 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); + + ig.Emit (OpCodes.Call, conversion_operator); + } + } + + // + // We need to special case this since an empty cast of + // a NullLiteral is still a Constant + // + public class NullCast : Constant { + protected Expression child; + + public NullCast (Expression child, Type return_type) + { + eclass = child.eclass; + type = return_type; + this.child = child; + } + + override public string AsString () + { + return "null"; + } + + public override object GetValue () + { + return null; + } + + public override Expression DoResolve (EmitContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; } public override void Emit (EmitContext ec) @@ -1501,6 +1306,17 @@ namespace Mono.CSharp { child.Emit (ec); } + public override Constant Increment () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { + throw new NotImplementedException (); + } + } + public override bool IsNegative { get { return false; @@ -1540,69 +1356,21 @@ namespace Mono.CSharp { return Child.GetValue (); } - public object GetValueAsEnumType () + public override object GetTypedValue () { + // FIXME: runtime is not ready to work with just emited enums + if (!RootContext.StdLib) { + return Child.GetValue (); + } + return System.Enum.ToObject (type, Child.GetValue ()); } - - // - // Converts from one of the valid underlying types for an enumeration - // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to - // one of the internal compiler literals: Int/UInt/Long/ULong Literals. - // - public Constant WidenToCompilerConstant () + + public override void Error_ValueCannotBeConverted (Location loc, Type t) { - Type t = TypeManager.EnumToUnderlying (Child.Type); - object v = ((Constant) Child).GetValue ();; - - if (t == TypeManager.int32_type) - return new IntConstant ((int) v); - if (t == TypeManager.uint32_type) - return new UIntConstant ((uint) v); - if (t == TypeManager.int64_type) - return new LongConstant ((long) v); - if (t == TypeManager.uint64_type) - return new ULongConstant ((ulong) v); - if (t == TypeManager.short_type) - return new ShortConstant ((short) v); - if (t == TypeManager.ushort_type) - return new UShortConstant ((ushort) v); - if (t == TypeManager.byte_type) - return new ByteConstant ((byte) v); - if (t == TypeManager.sbyte_type) - return new SByteConstant ((sbyte) v); - - throw new Exception ("Invalid enumeration underlying type: " + t); + Convert.Error_CannotImplicitConversion (loc, Type, t); } - // - // Extracts the value in the enumeration on its native representation - // - public object GetPlainValue () - { - Type t = TypeManager.EnumToUnderlying (Child.Type); - object v = ((Constant) Child).GetValue ();; - - if (t == TypeManager.int32_type) - return (int) v; - if (t == TypeManager.uint32_type) - return (uint) v; - if (t == TypeManager.int64_type) - return (long) v; - if (t == TypeManager.uint64_type) - return (ulong) v; - if (t == TypeManager.short_type) - return (short) v; - if (t == TypeManager.ushort_type) - return (ushort) v; - if (t == TypeManager.byte_type) - return (byte) v; - if (t == TypeManager.sbyte_type) - return (sbyte) v; - - return null; - } - public override string AsString () { return Child.AsString (); @@ -1637,7 +1405,18 @@ namespace Mono.CSharp { { return Child.ConvertToInt (); } - + + public override Constant Increment() + { + return new EnumConstant (Child.Increment (), type); + } + + public override bool IsDefaultValue { + get { + return Child.IsDefaultValue; + } + } + public override bool IsZeroInteger { get { return Child.IsZeroInteger; } } @@ -1647,6 +1426,27 @@ namespace Mono.CSharp { return Child.IsNegative; } } + + public override Constant ToType (Type type, Location loc) + { + if (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) + Child = Child.ToType (type.UnderlyingSystemType, loc); + return this; + } + + if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, this, type)){ + Error_ValueCannotBeConverted (loc, type); + return null; + } + + return Child.ToType (type, loc); + } + } /// @@ -1657,12 +1457,6 @@ namespace Mono.CSharp { /// public class BoxedCast : EmptyCast { - public BoxedCast (Expression expr) - : base (expr, TypeManager.object_type) - { - eclass = ExprClass.Value; - } - public BoxedCast (Expression expr, Type target_type) : base (expr, target_type) { @@ -2005,54 +1799,18 @@ namespace Mono.CSharp { } /// - /// SimpleName expressions are initially formed of a single - /// word and it only happens at the beginning of the expression. + /// SimpleName expressions are formed of a single word and only happen at the beginning + /// of a dotted-name. /// - /// - /// - /// The expression will try to be bound to a Field, a Method - /// group or a Property. If those fail we pass the name to our - /// caller and the SimpleName is compounded to perform a type - /// lookup. The idea behind this process is that we want to avoid - /// creating a namespace map from the assemblies, as that requires - /// the GetExportedTypes function to be called and a hashtable to - /// be constructed which reduces startup time. If later we find - /// that this is slower, we should create a `NamespaceExpr' expression - /// that fully participates in the resolution process. - /// - /// For example `System.Console.WriteLine' is decomposed into - /// MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine") - /// - /// The first SimpleName wont produce a match on its own, so it will - /// be turned into: - /// MemberAccess (SimpleName ("System.Console"), "WriteLine"). - /// - /// System.Console will produce a TypeExpr match. - /// - /// The downside of this is that we might be hitting `LookupType' too many - /// times with this scheme. - /// public class SimpleName : Expression { public string Name; public readonly TypeArguments Arguments; + bool in_transit; - // - // If true, then we are a simple name, not composed with a ". - // - bool is_base; - - public SimpleName (string a, string b, Location l) - { - Name = String.Concat (a, ".", b); - loc = l; - is_base = false; - } - public SimpleName (string name, Location l) { Name = name; loc = l; - is_base = true; } public SimpleName (string name, TypeArguments args, Location l) @@ -2060,138 +1818,205 @@ namespace Mono.CSharp { Name = name; Arguments = args; loc = l; - is_base = true; } - public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) + public SimpleName (string name, TypeParameter[] type_params, Location l) { - if (ec.IsFieldInitializer) - Report.Error ( - 236, l, - "A field initializer cannot reference the non-static field, " + - "method or property `"+name+"'"); - else - Report.Error ( - 120, l, - "An object reference is required " + - "for the non-static field `"+name+"'"); + Name = name; + loc = l; + + Arguments = new TypeArguments (l); + foreach (TypeParameter type_param in type_params) + Arguments.Add (new TypeParameterExpr (type_param, l)); } - - // - // Checks whether we are trying to access an instance - // property, method or field from a static body. - // - Expression MemberStaticCheck (EmitContext ec, Expression e) + + public static string RemoveGenericArity (string name) { - if (e is IMemberExpr){ - IMemberExpr member = (IMemberExpr) e; - - if (!member.IsStatic){ - Error_ObjectRefRequired (ec, loc, Name); - return null; + 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 e; + 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); + + 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); + } + public override Expression DoResolve (EmitContext ec) { - return SimpleNameResolve (ec, null, false, false); + return SimpleNameResolve (ec, null, false); } public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { - return SimpleNameResolve (ec, right_side, false, false); + return SimpleNameResolve (ec, right_side, false); } - public Expression DoResolveAllowStatic (EmitContext ec, bool intermediate) + public Expression DoResolve (EmitContext ec, bool intermediate) { - return SimpleNameResolve (ec, null, true, intermediate); + return SimpleNameResolve (ec, null, intermediate); } - public override Expression ResolveAsTypeStep (EmitContext ec) + private bool IsNestedChild (Type t, Type parent) { - DeclSpace ds = ec.DeclSpace; - NamespaceEntry ns = ds.NamespaceEntry; - Type t; - IAlias alias_value; + if (parent == null) + return false; - // - // Since we are cheating: we only do the Alias lookup for - // namespaces if the name does not include any dots in it - // - if (ns != null && is_base) - alias_value = ns.LookupAlias (Name); - else - alias_value = null; + while (parent != null) { + if (parent.IsGenericInstance) + parent = parent.GetGenericTypeDefinition (); - TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc); - if (generic_type != null) - return generic_type.ResolveAsTypeTerminal (ec); + if (TypeManager.IsNestedChildOf (t, parent)) + return true; - if (ec.ResolvingTypeTree){ - int errors = Report.Errors; - Type dt = ds.FindType (loc, Name); - - if (Report.Errors != errors) - return null; - - if (dt != null) - return new TypeExpression (dt, loc); - - if (alias_value != null){ - if (alias_value.IsType) - return alias_value.ResolveAsType (ec); - if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null) - return new TypeExpression (t, loc); - } + parent = parent.BaseType; } - if ((t = RootContext.LookupType (ds, Name, true, loc)) != null) - return new TypeExpression (t, loc); + return false; + } - if (alias_value != null) { - if (alias_value.IsType) - return alias_value.ResolveAsType (ec); - if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null) - return new TypeExpression (t, loc); - - // we have alias value, but it isn't Type, so try if it's namespace - return new SimpleName (alias_value.Name, loc); + FullNamedExpression ResolveNested (EmitContext ec, Type t) + { + if (!t.IsGenericTypeDefinition) + return null; + + DeclSpace ds = ec.DeclSpace; + while (ds != null) { + if (IsNestedChild (t, ds.TypeBuilder)) + break; + + ds = ds.Parent; } - // No match, maybe our parent can compose us - // into something meaningful. - return this; + if (ds == null) + return null; + + Type[] gen_params = t.GetGenericArguments (); + + 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; } - Expression SimpleNameResolve (EmitContext ec, Expression right_side, - bool allow_static, bool intermediate) + public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) { - Expression e = DoSimpleNameResolve (ec, right_side, allow_static, intermediate); - if (e == null) - return null; + FullNamedExpression fne = ec.DeclSpace.LookupGeneric (Name, loc); + if (fne != null) + return fne.ResolveAsTypeStep (ec, silent); - Block current_block = ec.CurrentBlock; - if (current_block != null){ - //LocalInfo vi = current_block.GetLocalInfo (Name); - if (is_base && - current_block.IsVariableNameUsedInChildBlock(Name)) { - Report.Error (135, Location, - "'{0}' has a different meaning in a " + - "child block", Name); - return null; + int errors = Report.Errors; + fne = ec.DeclSpace.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); + + if (Arguments != null) { + ConstructedType ct = new ConstructedType (fne, Arguments, loc); + return ct.ResolveAsTypeStep (ec); } + + return fne; } - if (e.Type != null && e.Type.IsPointer && !ec.InUnsafe) { - UnsafeError (loc); + if (silent || errors != Report.Errors) return null; + + MemberCore mc = ec.DeclSpace.GetDefinition (Name); + if (mc != null) { + Error_UnexpectedKind (ec, "type", GetMemberType (mc), loc); + } else { + NamespaceEntry.Error_NamespaceNotFound (loc, Name); } - return e; + return null; + } + + // TODO: I am still not convinced about this. If someone else will need it + // implement this as virtual property in MemberCore hierarchy + string GetMemberType (MemberCore mc) + { + if (mc is PropertyBase) + return "property"; + if (mc is Indexer) + return "indexer"; + if (mc is FieldBase) + return "field"; + + return "type"; + } + + Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate) + { + if (in_transit) + return null; + in_transit = true; + + Expression e = DoSimpleNameResolve (ec, right_side, intermediate); + if (e == null) + return null; + + if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location)) + return e; + + return null; } /// @@ -2200,7 +2025,7 @@ namespace Mono.CSharp { /// Local Variables and Parameters are handled at /// parse time, so they never occur as SimpleNames. /// - /// The `allow_static' flag is used by MemberAccess only + /// The `intermediate' flag is used by MemberAccess only /// and it is used to inform us that it is ok for us to /// avoid the static check, because MemberAccess might end /// up resolving the Name as a Type name and the access as @@ -2211,7 +2036,7 @@ namespace Mono.CSharp { /// Type is both an instance variable and a Type; Type.GetType /// is the static method not an instance method of type. /// - Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static, bool intermediate) + Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool intermediate) { Expression e = null; @@ -2222,20 +2047,21 @@ namespace Mono.CSharp { if (current_block != null){ LocalInfo vi = current_block.GetLocalInfo (Name); if (vi != null){ - Expression var; - - var = new LocalVariableReference (ec.CurrentBlock, Name, loc); - - if (right_side != null) - return var.ResolveLValue (ec, right_side); - else - return var.Resolve (ec); + LocalVariableReference var = new LocalVariableReference (ec.CurrentBlock, Name, loc); + if (right_side != null) { + return var.ResolveLValue (ec, right_side, loc); + } else { + ResolveFlags rf = ResolveFlags.VariableOrValue; + if (intermediate) + rf |= ResolveFlags.DisableFlowAnalysis; + return var.Resolve (ec, rf); + } } - ParameterReference pref = current_block.GetParameterReference (Name, loc); + ParameterReference pref = current_block.Toplevel.GetParameterReference (Name, loc); if (pref != null) { if (right_side != null) - return pref.ResolveLValue (ec, right_side); + return pref.ResolveLValue (ec, right_side, loc); else return pref.Resolve (ec); } @@ -2246,6 +2072,8 @@ namespace Mono.CSharp { // DeclSpace lookup_ds = ec.DeclSpace; + Type almost_matched_type = null; + ArrayList almost_matched = null; do { if (lookup_ds.TypeBuilder == null) break; @@ -2254,6 +2082,11 @@ namespace Mono.CSharp { if (e != null) break; + 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); @@ -2261,43 +2094,60 @@ namespace Mono.CSharp { e = MemberLookup (ec, ec.ContainerType, Name, loc); if (e == null) { - // - // Since we are cheating (is_base is our hint - // that we are the beginning of the name): we - // only do the Alias lookup for namespaces if - // the name does not include any dots in it - // - NamespaceEntry ns = ec.DeclSpace.NamespaceEntry; - if (is_base && ns != null){ - IAlias alias_value = ns.LookupAlias (Name); - if (alias_value != null){ - if (alias_value.IsType) - return alias_value.ResolveAsType (ec); - - Name = alias_value.Name; - Type t; - - if ((t = TypeManager.LookupType (Name)) != null) - return new TypeExpression (t, loc); - - // No match, maybe our parent can compose us - // into something meaningful. - return this; - } + if (almost_matched == null && almostMatchedMembers.Count > 0) { + almost_matched_type = ec.ContainerType; + almost_matched = (ArrayList) almostMatchedMembers.Clone (); } + e = ResolveAsTypeStep (ec, false); + } - return ResolveAsTypeStep (ec); + if (e == null) { + if (almost_matched != null) + 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); + return null; } if (e is TypeExpr) return e; - if (e is IMemberExpr) { - e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this); + if (e is MemberExpr) { + MemberExpr me = (MemberExpr) e; + + Expression left; + if (me.IsInstance) { + if (ec.IsStatic || ec.IsFieldInitializer) { + // + // Note that an MemberExpr can be both IsInstance and IsStatic. + // An unresolved MethodGroupExpr can contain both kinds of methods + // and each predicate is true if the MethodGroupExpr contains + // at least one of that kind of method. + // + + if (!me.IsStatic && + (!intermediate || !IdenticalNameAndTypeName (ec, me, loc))) { + Error_ObjectRefRequired (ec, loc, me.GetSignatureForError ()); + return null; + } + + // + // Pass the buck to MemberAccess and Invocation. + // + left = EmptyExpression.Null; + } else { + left = ec.GetThis (loc); + } + } else { + left = new TypeExpression (ec.ContainerType, loc); + } + + e = me.ResolveMemberAccess (ec, left, loc, null); if (e == null) return null; - IMemberExpr me = e as IMemberExpr; + me = e as MemberExpr; if (me == null) return e; @@ -2309,35 +2159,22 @@ namespace Mono.CSharp { return mg.ResolveGeneric (ec, Arguments); } - // This fails if ResolveMemberAccess() was unable to decide whether - // it's a field or a type of the same name. - - if (!me.IsStatic && (me.InstanceExpression == null)) - return e; - if (!me.IsStatic && TypeManager.IsNestedFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && me.InstanceExpression.Type != me.DeclaringType && !TypeManager.IsFamilyAccessible (me.InstanceExpression.Type, me.DeclaringType) && - (!intermediate || !MemberAccess.IdenticalNameAndTypeName (ec, this, e, loc))) { - Error (38, "Cannot access nonstatic member `" + me.Name + "' of " + - "outer type `" + me.DeclaringType + "' via nested type `" + - me.InstanceExpression.Type + "'"); + (!intermediate || !IdenticalNameAndTypeName (ec, e, loc))) { + Report.Error (38, loc, "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", + TypeManager.CSharpName (me.DeclaringType), TypeManager.CSharpName (me.InstanceExpression.Type)); return null; } return (right_side != null) - ? e.DoResolveLValue (ec, right_side) - : e.DoResolve (ec); + ? me.DoResolveLValue (ec, right_side) + : me.DoResolve (ec); } - if (ec.IsStatic || ec.IsFieldInitializer){ - if (allow_static) - return e; - - return MemberStaticCheck (ec, e); - } else - return e; + return e; } public override void Emit (EmitContext ec) @@ -2356,13 +2193,33 @@ namespace Mono.CSharp { { return Name; } + + public override string GetSignatureForError () + { + return Name; + } + } + + /// + /// Represents a namespace or a type. The name of the class was inspired by + /// section 10.8.1 (Fully Qualified Names). + /// + public abstract class FullNamedExpression : Expression { + public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) + { + return this; + } + + public abstract string FullName { + get; + } } /// /// Fully resolved expression that evaluates to a type /// - public abstract class TypeExpr : Expression, IAlias { - override public Expression ResolveAsTypeStep (EmitContext ec) + public abstract class TypeExpr : FullNamedExpression { + override public FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent) { TypeExpr t = DoResolveAsTypeStep (ec); if (t == null) @@ -2420,15 +2277,17 @@ namespace Mono.CSharp { return true; } - public virtual bool IsAttribute { - get { - return Type == TypeManager.attribute_type || - Type.IsSubclassOf (TypeManager.attribute_type); - } - } - protected abstract TypeExpr DoResolveAsTypeStep (EmitContext ec); + public virtual Type ResolveType (EmitContext ec) + { + TypeExpr t = ResolveAsTypeTerminal (ec); + if (t == null) + return null; + + return t.Type; + } + public abstract string Name { get; } @@ -2451,18 +2310,9 @@ namespace Mono.CSharp { { return Name; } - - bool IAlias.IsType { - get { return true; } - } - - TypeExpr IAlias.ResolveAsType (EmitContext ec) - { - return ResolveAsTypeTerminal (ec); - } } - public class TypeExpression : TypeExpr, IAlias { + public class TypeExpression : TypeExpr { public TypeExpression (Type t, Location l) { Type = t; @@ -2476,15 +2326,11 @@ namespace Mono.CSharp { } public override string Name { - get { - return Type.ToString (); - } + get { return Type.ToString (); } } - string IAlias.Name { - get { - return Type.FullName != null ? Type.FullName : Type.Name; - } + public override string FullName { + get { return Type.FullName; } } } @@ -2501,22 +2347,73 @@ namespace Mono.CSharp { this.name = name; } + static readonly char [] dot_array = { '.' }; protected override TypeExpr DoResolveAsTypeStep (EmitContext ec) { - if (type == null) { - type = RootContext.LookupType ( - ec.DeclSpace, name, false, Location.Null); - if (type == null) - return null; + if (type != null) + return this; + + // 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 = Namespace.Root.Lookup (ec.DeclSpace, 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.DeclSpace, element, Location.Null); + } + + if (resolved != null && resolved is TypeExpr) { + Type t = ((TypeExpr) resolved).Type; + while (t != null) { + if (!ec.DeclSpace.CheckAccessLevel (t)) { + resolved = null; + lookup_name = t.FullName; + break; + } + if (i == count) { + type = t; + return this; + } + t = TypeManager.GetNestedType (t, elements [i++]); + } + } + } + + if (resolved == null) { + NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name); + return null; } + if (!(resolved is TypeExpr)) { + resolved.Error_UnexpectedKind (ec, "type", loc); + return null; + } + + type = ((TypeExpr) resolved).ResolveType (ec); return this; } public override string Name { - get { - return name; - } + get { return name; } + } + + public override string FullName { + get { return name; } } } @@ -2524,19 +2421,50 @@ namespace Mono.CSharp { /// Represents an "unbound generic type", ie. typeof (Foo<>). /// See 14.5.11. /// - public class UnboundTypeExpression : TypeLookupExpression { - public UnboundTypeExpression (string name) - : base (name) - { } + public class UnboundTypeExpression : TypeExpr + { + MemberName name; + + public UnboundTypeExpression (MemberName name, Location l) + { + this.name = name; + loc = l; + } + + protected override TypeExpr DoResolveAsTypeStep (EmitContext ec) + { + Expression expr; + if (name.Left != null) { + Expression lexpr = name.Left.GetTypeExpression (); + expr = new MemberAccess (lexpr, name.Basename, loc); + } else { + expr = new SimpleName (name.Basename, loc); + } + + FullNamedExpression fne = expr.ResolveAsTypeStep (ec); + 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, IAlias { - IAlias alias; + public class TypeAliasExpression : TypeExpr { + FullNamedExpression alias; TypeExpr texpr; TypeArguments args; string name; - public TypeAliasExpression (IAlias alias, TypeArguments args, Location l) + public TypeAliasExpression (FullNamedExpression alias, TypeArguments args, Location l) { this.alias = alias; this.args = args; @@ -2544,18 +2472,22 @@ namespace Mono.CSharp { eclass = ExprClass.Type; if (args != null) - name = alias.Name + "<" + args.ToString () + ">"; + name = alias.FullName + "<" + args.ToString () + ">"; else - name = alias.Name; + name = alias.FullName; } public override string Name { + get { return alias.FullName; } + } + + public override string FullName { get { return name; } } protected override TypeExpr DoResolveAsTypeStep (EmitContext ec) { - texpr = alias.ResolveAsType (ec); + texpr = alias.ResolveAsTypeTerminal (ec); if (texpr == null) return null; @@ -2584,34 +2516,136 @@ namespace Mono.CSharp { return new TypeExpression (type, loc); } - public override bool CheckAccessLevel (DeclSpace ds) + public override bool CheckAccessLevel (DeclSpace ds) + { + return texpr.CheckAccessLevel (ds); + } + + public override bool AsAccessible (DeclSpace ds, int flags) + { + return texpr.AsAccessible (ds, flags); + } + + public override bool IsClass { + get { return texpr.IsClass; } + } + + public override bool IsValueType { + get { return texpr.IsValueType; } + } + + public override bool IsInterface { + get { return texpr.IsInterface; } + } + + public override bool IsSealed { + get { return texpr.IsSealed; } + } + } + + /// + /// This class denotes an expression which evaluates to a member + /// of a struct or a class. + /// + public abstract class MemberExpr : Expression + { + /// + /// The name of this member. + /// + public abstract string Name { + get; + } + + /// + /// Whether this is an instance member. + /// + public abstract bool IsInstance { + get; + } + + /// + /// Whether this is a static member. + /// + public abstract bool IsStatic { + get; + } + + /// + /// The type which declares this member. + /// + public abstract Type DeclaringType { + get; + } + + /// + /// The instance expression associated with this member, if it's a + /// non-static member. + /// + public Expression InstanceExpression; + + public static void error176 (Location loc, string name) { - return texpr.CheckAccessLevel (ds); + Report.Error (176, loc, "Static member `{0}' cannot be accessed " + + "with an instance reference, qualify it with a type name instead", name); } - public override bool AsAccessible (DeclSpace ds, int flags) + + // TODO: possible optimalization + // Cache resolved constant result in FieldBuilder <-> expression map + public virtual Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc, + SimpleName original) { - return texpr.AsAccessible (ds, flags); - } + // + // Precondition: + // original == null || original.Resolve (...) ==> left + // - public override bool IsClass { - get { return texpr.IsClass; } - } + if (left is TypeExpr) { + if (!IsStatic) { + SimpleName.Error_ObjectRefRequired (ec, loc, Name); + return null; + } - public override bool IsValueType { - get { return texpr.IsValueType; } - } + return this; + } + + if (!IsInstance) { + if (original != null && original.IdenticalNameAndTypeName (ec, left, loc)) + return this; - public override bool IsInterface { - get { return texpr.IsInterface; } - } + error176 (loc, GetSignatureForError ()); + return null; + } - public override bool IsSealed { - get { return texpr.IsSealed; } + InstanceExpression = left; + + return this; } - public override bool IsAttribute { - get { return texpr.IsAttribute; } + protected void EmitInstance (EmitContext ec, bool prepare_for_load) + { + if (IsStatic) + return; + + if (InstanceExpression == EmptyExpression.Null) { + SimpleName.Error_ObjectRefRequired (ec, loc, Name); + return; + } + + if (InstanceExpression.Type.IsValueType) { + if (InstanceExpression is IMemoryLocation) { + ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.LoadStore); + } else { + LocalTemporary t = new LocalTemporary (ec, InstanceExpression.Type); + InstanceExpression.Emit (ec); + t.Store (ec); + t.AddressOf (ec, AddressOp.Store); + } + } else + InstanceExpression.Emit (ec); + + if (prepare_for_load) + ec.ig.Emit (OpCodes.Dup); } } @@ -2620,10 +2654,8 @@ namespace Mono.CSharp { /// /// This is a fully resolved expression that evaluates to a type /// - public class MethodGroupExpr : Expression, IMemberExpr { + public class MethodGroupExpr : MemberExpr { public MethodBase [] Methods; - Expression instance_expression = null; - bool is_explicit_impl = false; bool has_type_arguments = false; bool identical_type_name = false; bool is_base; @@ -2658,7 +2690,7 @@ namespace Mono.CSharp { type = TypeManager.object_type; } - public Type DeclaringType { + public override Type DeclaringType { get { // // We assume that the top-level type is in the end @@ -2667,29 +2699,6 @@ namespace Mono.CSharp { //return Methods [0].DeclaringType; } } - - // - // `A method group may have associated an instance expression' - // - public Expression InstanceExpression { - get { - return instance_expression; - } - - set { - instance_expression = value; - } - } - - public bool IsExplicitImpl { - get { - return is_explicit_impl; - } - - set { - is_explicit_impl = value; - } - } public bool HasTypeArguments { get { @@ -2720,14 +2729,18 @@ namespace Mono.CSharp { } } - public string Name { + public override string GetSignatureForError () + { + return TypeManager.CSharpSignature (Methods [0]); + } + + public override string Name { get { - //return Methods [0].Name; - return Methods [Methods.Length - 1].Name; + return Methods [0].Name; } } - public bool IsInstance { + public override bool IsInstance { get { foreach (MethodBase mb in Methods) if (!mb.IsStatic) @@ -2737,7 +2750,7 @@ namespace Mono.CSharp { } } - public bool IsStatic { + public override bool IsStatic { get { foreach (MethodBase mb in Methods) if (mb.IsStatic) @@ -2746,15 +2759,25 @@ namespace Mono.CSharp { return false; } } + + public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc, + SimpleName original) + { + if (!(left is TypeExpr) && + original != null && original.IdenticalNameAndTypeName (ec, left, loc)) + IdenticalTypeName = true; + + return base.ResolveMemberAccess (ec, left, loc, original); + } override public Expression DoResolve (EmitContext ec) { if (!IsInstance) - instance_expression = null; + InstanceExpression = null; - if (instance_expression != null) { - instance_expression = instance_expression.DoResolve (ec); - if (instance_expression == null) + if (InstanceExpression != null) { + InstanceExpression = InstanceExpression.DoResolve (ec); + if (InstanceExpression == null) return null; } @@ -2834,7 +2857,7 @@ namespace Mono.CSharp { if (gen_params.Length != atypes.Length) continue; - list.Add (mi.BindGenericParameters (atypes)); + list.Add (mi.MakeGenericMethod (atypes)); } if (list.Count > 0) { @@ -2861,14 +2884,19 @@ namespace Mono.CSharp { /// /// Fully resolved expression that evaluates to a Field /// - public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr, IVariable { + public class FieldExpr : MemberExpr, IAssignMethod, IMemoryLocation, IVariable { public readonly FieldInfo FieldInfo; - Expression instance_expr; VariableInfo variable_info; LocalTemporary temp; bool prepared; - bool is_field_initializer; + bool in_initializer; + + public FieldExpr (FieldInfo fi, Location l, bool in_initializer): + this (fi, l) + { + this.in_initializer = in_initializer; + } public FieldExpr (FieldInfo fi, Location l) { @@ -2878,60 +2906,111 @@ namespace Mono.CSharp { loc = l; } - public string Name { + public override string Name { get { return FieldInfo.Name; } } - public bool IsInstance { + public override bool IsInstance { get { return !FieldInfo.IsStatic; } } - public bool IsStatic { + public override bool IsStatic { get { return FieldInfo.IsStatic; } } - public Type DeclaringType { + public override Type DeclaringType { get { return FieldInfo.DeclaringType; } } - public Expression InstanceExpression { - get { - return instance_expr; - } - - set { - instance_expr = value; - } + public override string GetSignatureForError () + { + return TypeManager.GetFullNameSignature (FieldInfo); } - public bool IsFieldInitializer { + public VariableInfo VariableInfo { get { - return is_field_initializer; + return variable_info; } + } - set { - is_field_initializer = value; + public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc, + SimpleName original) + { + FieldInfo fi = FieldInfo.Mono_GetGenericFieldDefinition (); + + if (fi.IsLiteral) { + IConstant ic = TypeManager.GetConstant (fi); + if (ic == null) { + ic = new ExternalConstant (fi); + TypeManager.RegisterConstant (fi, ic); + } + + bool left_is_type = left is TypeExpr; + if (!left_is_type && (original == null || !original.IdenticalNameAndTypeName (ec, left, loc))) { + Report.SymbolRelatedToPreviousError (FieldInfo); + error176 (loc, TypeManager.GetFullNameSignature (FieldInfo)); + return null; + } + + if (ic.ResolveValue ()) + ic.CheckObsoleteness (loc); + + return ic.Value; } - } - public VariableInfo VariableInfo { - get { - return variable_info; + bool is_emitted = fi is FieldBuilder; + Type t = fi.FieldType; + + // + // Decimal constants cannot be encoded in the constant blob, and thus are marked + // as IsInitOnly ('readonly' in C# parlance). We get its value from the + // DecimalConstantAttribute metadata. + // + if (fi.IsInitOnly && !is_emitted && t == TypeManager.decimal_type) { + object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false); + if (attrs.Length == 1) + return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value); + } + + if (t.IsPointer && !ec.InUnsafe) { + UnsafeError (loc); + return null; } + + return base.ResolveMemberAccess (ec, left, loc, original); } 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; + } + if (!FieldInfo.IsStatic){ - if (instance_expr == null){ + if (InstanceExpression == null){ // // This can happen when referencing an instance field using // a fully qualified type expression: TypeName.InstanceField = xxx @@ -2943,37 +3022,41 @@ namespace Mono.CSharp { // 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. - instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue | - ResolveFlags.DisableFlowAnalysis); - if (instance_expr == null) + InstanceExpression = InstanceExpression.Resolve ( + ec, ResolveFlags.VariableOrValue | ResolveFlags.DisableFlowAnalysis); + if (InstanceExpression == null) return null; } - ObsoleteAttribute oa; - FieldBase f = TypeManager.GetField (FieldInfo); - if (f != null) { - oa = f.GetObsoleteAttribute (f.Parent); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc); - // To be sure that type is external because we do not register generated fields - } else if (!(FieldInfo.DeclaringType is TypeBuilder)) { - oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo); - if (oa != null) - AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc); + if (!in_initializer) { + ObsoleteAttribute oa; + FieldBase f = TypeManager.GetField (FieldInfo); + if (f != null) { + f.CheckObsoleteness (loc); + // To be sure that type is external because we do not register generated fields + } else if (!(FieldInfo.DeclaringType is TypeBuilder)) { + oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc); + } } - if (ec.CurrentAnonymousMethod != null){ + AnonymousContainer am = ec.CurrentAnonymousMethod; + if (am != null){ if (!FieldInfo.IsStatic){ - if (ec.TypeContainer is Struct){ - Report.Error (1673, loc, "Can not reference instance variables in anonymous methods hosted in structs"); + if (!am.IsIterator && (ec.TypeContainer is Struct)){ + Report.Error (1673, loc, + "Anonymous methods inside structs cannot access instance members of `{0}'. Consider copying `{0}' to a local variable outside the anonymous method and using the local instead", + "this"); return null; } - ec.CaptureField (this); - } + if ((am.ContainerAnonymousMethod == null) && (InstanceExpression is This)) + ec.CaptureField (this); + } } // If the instance expression is a local variable or parameter. - IVariable var = instance_expr as IVariable; + IVariable var = InstanceExpression as IVariable; if ((var == null) || (var.VariableInfo == null)) return this; @@ -2990,18 +3073,16 @@ namespace Mono.CSharp { string msg; if (is_instance) - msg = "Readonly field can not be assigned outside " + - "of constructor or variable initializer"; + msg = "A readonly field cannot be assigned to (except in a constructor or a variable initializer)"; else - msg = "A static readonly field can only be assigned in " + - "a static constructor"; + msg = "A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)"; Report.Error (is_instance ? 191 : 198, loc, msg); } override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { - IVariable var = instance_expr as IVariable; + IVariable var = InstanceExpression as IVariable; if ((var != null) && (var.VariableInfo != null)) var.VariableInfo.SetFieldAssigned (ec, FieldInfo.Name); @@ -3010,19 +3091,19 @@ namespace Mono.CSharp { if (e == null) return null; - if (!FieldInfo.IsStatic && (instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation))) { - // FIXME: Provide better error reporting. - Error (1612, "Cannot modify expression because it is not a variable."); + if (!FieldInfo.IsStatic && (InstanceExpression.Type.IsValueType && !(InstanceExpression is IMemoryLocation))) { + Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", + InstanceExpression.GetSignatureForError ()); return null; } - if (!FieldInfo.IsInitOnly) - return this; - FieldBase fb = TypeManager.GetField (FieldInfo); if (fb != null) fb.SetAssigned (); + if (!FieldInfo.IsInitOnly) + return this; + // // InitOnly fields can only be assigned in constructors // @@ -3032,8 +3113,7 @@ namespace Mono.CSharp { Report_AssignToReadonly (false); Type ctype; - if (!is_field_initializer && - (ec.TypeContainer.CurrentType != null)) + if (ec.TypeContainer.CurrentType != null) ctype = ec.TypeContainer.CurrentType; else ctype = ec.ContainerType; @@ -3051,17 +3131,38 @@ namespace Mono.CSharp { { if (!IsStatic && Type.IsValueType && !container.IsSubclassOf (TypeManager.mbr_type) && DeclaringType.IsSubclassOf (TypeManager.mbr_type)) { Report.SymbolRelatedToPreviousError (DeclaringType); - Report.Error (1690, loc, "Cannot call '{0}' method, property, or indexer because it is a value type member of a marshal-by-reference class", Name); + 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 ()); } } - public bool VerifyFixed (bool is_expression) + public bool VerifyFixed () + { + IVariable variable = InstanceExpression as IVariable; + // A variable of the form V.I is fixed when V is a fixed variable of a struct type. + // We defer the InstanceExpression check after the variable check to avoid a + // separate null check on InstanceExpression. + return variable != null && InstanceExpression.Type.IsValueType && variable.VerifyFixed (); + } + + public override int GetHashCode() + { + return FieldInfo.GetHashCode (); + } + + public override bool Equals (object obj) { - IVariable variable = instance_expr as IVariable; - if ((variable == null) || !variable.VerifyFixed (true)) + FieldExpr fe = obj as FieldExpr; + if (fe == null) return false; - return true; + if (FieldInfo != fe.FieldInfo) + return false; + + if (InstanceExpression == null || fe.InstanceExpression == null) + return true; + + return InstanceExpression.Equals (fe.InstanceExpression); } public void Emit (EmitContext ec, bool leave_copy) @@ -3069,13 +3170,14 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; bool is_volatile = false; - if (FieldInfo is FieldBuilder){ - FieldBase f = TypeManager.GetField (FieldInfo); + FieldInfo the_fi = FieldInfo.Mono_GetGenericFieldDefinition (); + if (the_fi is FieldBuilder){ + FieldBase f = TypeManager.GetField (the_fi); if (f != null){ if ((f.ModFlags & Modifiers.VOLATILE) != 0) is_volatile = true; - f.status |= Field.Status.USED; + f.SetMemberIsUsed (); } } @@ -3086,12 +3188,20 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ldsfld, FieldInfo); } else { if (!prepared) - EmitInstance (ec); + EmitInstance (ec, false); if (is_volatile) ig.Emit (OpCodes.Volatile); - ig.Emit (OpCodes.Ldfld, FieldInfo); + IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo); + if (ff != null) + { + ig.Emit (OpCodes.Ldflda, FieldInfo); + ig.Emit (OpCodes.Ldflda, ff.Element); + } + else { + ig.Emit (OpCodes.Ldfld, FieldInfo); + } } if (leave_copy) { @@ -3116,11 +3226,7 @@ namespace Mono.CSharp { return; } - if (!is_static) { - EmitInstance (ec); - if (prepare_for_load) - ig.Emit (OpCodes.Dup); - } + EmitInstance (ec, prepare_for_load); source.Emit (ec); if (leave_copy) { @@ -3137,7 +3243,7 @@ namespace Mono.CSharp { if ((f.ModFlags & Modifiers.VOLATILE) != 0) ig.Emit (OpCodes.Volatile); - f.status |= Field.Status.ASSIGNED; + f.SetAssigned (); } } @@ -3150,21 +3256,6 @@ namespace Mono.CSharp { temp.Emit (ec); } - void EmitInstance (EmitContext ec) - { - if (instance_expr.Type.IsValueType) { - if (instance_expr is IMemoryLocation) { - ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore); - } else { - LocalTemporary t = new LocalTemporary (ec, instance_expr.Type); - instance_expr.Emit (ec); - t.Store (ec); - t.AddressOf (ec, AddressOp.Store); - } - } else - instance_expr.Emit (ec); - } - public override void Emit (EmitContext ec) { Emit (ec, false); @@ -3178,14 +3269,15 @@ namespace Mono.CSharp { FieldBase f = TypeManager.GetField (FieldInfo); if (f != null){ if ((f.ModFlags & Modifiers.VOLATILE) != 0){ - Error (676, "volatile variable: can not take its address, or pass as ref/out parameter"); + 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.status |= Field.Status.ASSIGNED; + f.SetAssigned (); if ((mode & AddressOp.Load) != 0) - f.status |= Field.Status.USED; + f.SetMemberIsUsed (); } } @@ -3219,7 +3311,7 @@ namespace Mono.CSharp { if (FieldInfo.IsStatic){ ig.Emit (OpCodes.Ldsflda, FieldInfo); } else { - EmitInstance (ec); + EmitInstance (ec, false); ig.Emit (OpCodes.Ldflda, FieldInfo); } } @@ -3246,7 +3338,7 @@ namespace Mono.CSharp { /// This is not an LValue because we need to re-write the expression, we /// can not take data from the stack and store it. /// - public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr { + public class PropertyExpr : MemberExpr, IAssignMethod { public readonly PropertyInfo PropertyInfo; // @@ -3255,8 +3347,9 @@ namespace Mono.CSharp { public bool IsBase; MethodInfo getter, setter; bool is_static; + + bool resolved; - Expression instance_expr; LocalTemporary temp; bool prepared; @@ -3274,53 +3367,33 @@ namespace Mono.CSharp { ResolveAccessors (ec); } - public string Name { + public override string Name { get { return PropertyInfo.Name; } } - public bool IsInstance { + public override bool IsInstance { get { return !is_static; } } - public bool IsStatic { + public override bool IsStatic { get { return is_static; } } - public Type DeclaringType { + public override Type DeclaringType { get { return PropertyInfo.DeclaringType; } } - // - // The instance expression associated with this expression - // - public Expression InstanceExpression { - set { - instance_expr = value; - } - - get { - return instance_expr; - } - } - - public bool VerifyAssignable () + public override string GetSignatureForError () { - if (setter == null) { - Report.Error (200, loc, - "The property `" + PropertyInfo.Name + - "' can not be assigned to, as it has not set accessor"); - return false; - } - - return true; + return TypeManager.GetFullNameSignature (PropertyInfo); } void FindAccessors (Type invocation_type) @@ -3366,11 +3439,19 @@ namespace Mono.CSharp { FindAccessors (ec.ContainerType); if (getter != null) { + IMethodData md = TypeManager.GetMethod (getter); + if (md != null) + md.SetMemberIsUsed (); + AccessorTable [getter] = PropertyInfo; is_static = getter.IsStatic; } if (setter != null) { + IMethodData md = TypeManager.GetMethod (setter); + if (md != null) + md.SetMemberIsUsed (); + AccessorTable [setter] = PropertyInfo; is_static = setter.IsStatic; } @@ -3378,26 +3459,29 @@ namespace Mono.CSharp { bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check) { - if ((instance_expr == null) && ec.IsStatic && !is_static) { + if (is_static) { + InstanceExpression = null; + return true; + } + + if (InstanceExpression == null) { SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name); return false; } - if (instance_expr != null) { - instance_expr = instance_expr.DoResolve (ec); - if (instance_expr == null) - return false; - - instance_expr.CheckMarshallByRefAccess (ec.ContainerType); - } + InstanceExpression = InstanceExpression.DoResolve (ec); + if (InstanceExpression == null) + return false; + + InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType); - if (must_do_cs1540_check && (instance_expr != null)) { - if ((instance_expr.Type != ec.ContainerType) && - ec.ContainerType.IsSubclassOf (instance_expr.Type)) { + if (must_do_cs1540_check && InstanceExpression != EmptyExpression.Null) { + if ((InstanceExpression.Type != ec.ContainerType) && + ec.ContainerType.IsSubclassOf (InstanceExpression.Type)) { Report.Error (1540, loc, "Cannot access protected member `" + PropertyInfo.DeclaringType + "." + PropertyInfo.Name + "' via a qualifier of type `" + - TypeManager.CSharpName (instance_expr.Type) + + TypeManager.CSharpName (InstanceExpression.Type) + "'; the qualifier must be of type `" + TypeManager.CSharpName (ec.ContainerType) + "' (or derived from it)"); @@ -3407,15 +3491,35 @@ namespace Mono.CSharp { return true; } + + void Error_PropertyNotFound (MethodInfo mi, bool getter) + { + // TODO: correctly we should compare arguments but it will lead to bigger changes + if (mi is MethodBuilder) { + Error_TypeDoesNotContainDefinition (loc, PropertyInfo.DeclaringType, Name); + return; + } + + StringBuilder sig = new StringBuilder (TypeManager.CSharpName (mi.DeclaringType)); + sig.Append ('.'); + ParameterData iparams = TypeManager.GetParameterData (mi); + sig.Append (getter ? "get_" : "set_"); + sig.Append (Name); + sig.Append (iparams.GetSignatureForError ()); + + Report.SymbolRelatedToPreviousError (mi); + Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly", + Name, sig.ToString ()); + } override public Expression DoResolve (EmitContext ec) { + if (resolved) + return this; + if (getter != null){ if (TypeManager.GetArgumentTypes (getter).Length != 0){ - Report.Error ( - 117, loc, "`{0}' does not contain a " + - "definition for `{1}'.", getter.DeclaringType, - Name); + Error_PropertyNotFound (getter, true); return null; } } @@ -3429,17 +3533,25 @@ namespace Mono.CSharp { // if (setter == null) return null; - - Report.Error (154, loc, - "The property `" + PropertyInfo.Name + - "' can not be used in " + - "this context because it lacks a get accessor"); - return null; + + if (InstanceExpression != EmptyExpression.Null) { + Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor", + TypeManager.GetFullNameSignature (PropertyInfo)); + return null; + } } - bool must_do_cs1540_check; - if (!IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) { - Report.Error (122, loc, "'{0}.get' is inaccessible due to its protection level", PropertyInfo.Name); + bool must_do_cs1540_check = false; + if (getter != null && + !IsAccessorAccessible (ec.ContainerType, getter, out must_do_cs1540_check)) { + PropertyBase.PropertyMethod pm = TypeManager.GetMethod (getter) as PropertyBase.PropertyMethod; + if (pm != null && pm.HasCustomAccessModifier) { + Report.SymbolRelatedToPreviousError (pm); + Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible", + TypeManager.CSharpSignature (getter)); + } + else + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (getter)); return null; } @@ -3449,12 +3561,18 @@ namespace Mono.CSharp { // // Only base will allow this invocation to happen. // - if (IsBase && getter.IsAbstract){ - Report.Error (205, loc, "Cannot call an abstract base property: " + - PropertyInfo.DeclaringType + "." +PropertyInfo.Name); + if (IsBase && getter.IsAbstract) { + Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo)); return null; } + if (PropertyInfo.PropertyType.IsPointer && !ec.InUnsafe){ + UnsafeError (loc); + return null; + } + + resolved = true; + return this; } @@ -3470,24 +3588,26 @@ namespace Mono.CSharp { if (getter == null) return null; - Report.Error (154, loc, - "The property `" + PropertyInfo.Name + - "' can not be used in " + - "this context because it lacks a set accessor"); + Report.Error (200, loc, " Property or indexer `{0}' cannot be assigned to (it is read only)", + TypeManager.GetFullNameSignature (PropertyInfo)); return null; } if (TypeManager.GetArgumentTypes (setter).Length != 1){ - Report.Error ( - 117, loc, "`{0}' does not contain a " + - "definition for `{1}'.", getter.DeclaringType, - Name); + Error_PropertyNotFound (setter, false); return null; } bool must_do_cs1540_check; if (!IsAccessorAccessible (ec.ContainerType, setter, out must_do_cs1540_check)) { - Report.Error (122, loc, "'{0}.set' is inaccessible due to its protection level", PropertyInfo.Name); + PropertyBase.PropertyMethod pm = TypeManager.GetMethod (setter) as PropertyBase.PropertyMethod; + if (pm != null && pm.HasCustomAccessModifier) { + Report.SymbolRelatedToPreviousError (pm); + Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible", + TypeManager.CSharpSignature (setter)); + } + else + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (setter)); return null; } @@ -3498,63 +3618,38 @@ namespace Mono.CSharp { // Only base will allow this invocation to happen. // if (IsBase && setter.IsAbstract){ - Report.Error (205, loc, "Cannot call an abstract base property: " + - PropertyInfo.DeclaringType + "." +PropertyInfo.Name); + Error_CannotCallAbstractBase (TypeManager.GetFullNameSignature (PropertyInfo)); return null; } // // Check that we are not making changes to a temporary memory location // - if (instance_expr != null && instance_expr.Type.IsValueType && !(instance_expr is IMemoryLocation)) { - // FIXME: Provide better error reporting. - Error (1612, "Cannot modify expression because it is not a variable."); + if (InstanceExpression != null && InstanceExpression.Type.IsValueType && !(InstanceExpression is IMemoryLocation)) { + Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable", + InstanceExpression.GetSignatureForError ()); return null; } return this; } - - public override void Emit (EmitContext ec) { Emit (ec, false); } - void EmitInstance (EmitContext ec) - { - if (is_static) - return; - - if (instance_expr.Type.IsValueType) { - if (instance_expr is IMemoryLocation) { - ((IMemoryLocation) instance_expr).AddressOf (ec, AddressOp.LoadStore); - } else { - LocalTemporary t = new LocalTemporary (ec, instance_expr.Type); - instance_expr.Emit (ec); - t.Store (ec); - t.AddressOf (ec, AddressOp.Store); - } - } else - instance_expr.Emit (ec); - - if (prepared) - ec.ig.Emit (OpCodes.Dup); - } - - public void Emit (EmitContext ec, bool leave_copy) { if (!prepared) - EmitInstance (ec); + EmitInstance (ec, false); // // Special case: length of single dimension array property is turned into ldlen // if ((getter == TypeManager.system_int_array_get_length) || (getter == TypeManager.int_array_get_length)){ - Type iet = instance_expr.Type; + Type iet = InstanceExpression.Type; // // System.Array.Length can be called, but the Type does not @@ -3586,7 +3681,7 @@ namespace Mono.CSharp { { prepared = prepare_for_load; - EmitInstance (ec); + EmitInstance (ec, prepare_for_load); source.Emit (ec); if (leave_copy) { @@ -3605,20 +3700,13 @@ namespace Mono.CSharp { if (temp != null) temp.Emit (ec); } - - override public void EmitStatement (EmitContext ec) - { - Emit (ec); - ec.ig.Emit (OpCodes.Pop); - } } /// /// Fully resolved expression that evaluates to an Event /// - public class EventExpr : Expression, IMemberExpr { + public class EventExpr : MemberExpr { public readonly EventInfo EventInfo; - Expression instance_expr; bool is_static; MethodInfo add_accessor, remove_accessor; @@ -3643,63 +3731,83 @@ namespace Mono.CSharp { type = EventInfo.EventHandlerType; } - public string Name { + public override string Name { get { return EventInfo.Name; } } - public bool IsInstance { + public override bool IsInstance { get { return !is_static; } } - public bool IsStatic { + public override bool IsStatic { get { return is_static; } } - public Type DeclaringType { + public override Type DeclaringType { get { return EventInfo.DeclaringType; } } - public Expression InstanceExpression { - get { - return instance_expr; - } + public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc, + SimpleName original) + { + // + // If the event is local to this class, we transform ourselves into a FieldExpr + // - set { - instance_expr = value; + if (EventInfo.DeclaringType == ec.ContainerType || + TypeManager.IsNestedChildOf(ec.ContainerType, EventInfo.DeclaringType)) { + MemberInfo mi = TypeManager.GetPrivateFieldOfEvent (EventInfo); + + if (mi != null) { + MemberExpr ml = (MemberExpr) ExprClassFromMemberInfo (ec, mi, loc); + + if (ml == null) { + Report.Error (-200, loc, "Internal error!!"); + return null; + } + + InstanceExpression = null; + + return ml.ResolveMemberAccess (ec, left, loc, original); + } } + + return base.ResolveMemberAccess (ec, left, loc, original); } + bool InstanceResolve (EmitContext ec, bool must_do_cs1540_check) { - if ((instance_expr == null) && ec.IsStatic && !is_static) { + if (is_static) { + InstanceExpression = null; + return true; + } + + if (InstanceExpression == null) { SimpleName.Error_ObjectRefRequired (ec, loc, EventInfo.Name); return false; } - if (instance_expr != null) { - instance_expr = instance_expr.DoResolve (ec); - if (instance_expr == null) - return false; - } + InstanceExpression = InstanceExpression.DoResolve (ec); + if (InstanceExpression == null) + return false; // // 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 && (instance_expr != null)) { - if ((instance_expr.Type != ec.ContainerType) && - ec.ContainerType.IsSubclassOf (instance_expr.Type)) { - Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", - DeclaringType.Name + "." + EventInfo.Name); - + 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; } } @@ -3707,21 +3815,18 @@ namespace Mono.CSharp { return true; } - public override Expression DoResolve (EmitContext ec) + public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { - if (instance_expr != null) { - instance_expr = instance_expr.DoResolve (ec); - if (instance_expr == null) - return null; - } + return DoResolve (ec); + } + public override Expression DoResolve (EmitContext ec) + { 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.Error (122, loc, "'{0}' is inaccessible due to its protection level", - DeclaringType.Name + "." + EventInfo.Name); - return null; + if (!(IsAccessorAccessible (ec.ContainerType, add_accessor, out must_do_cs1540_check) && + IsAccessorAccessible (ec.ContainerType, remove_accessor, out must_do_cs1540_check))) { + ErrorIsInaccesible (loc, TypeManager.CSharpSignature (EventInfo)); + return null; } if (!InstanceResolve (ec, must_do_cs1540_check)) @@ -3732,13 +3837,18 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - if (instance_expr is This) - Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=, try calling the actual delegate", Name); + if (InstanceExpression is This) + Report.Error (79, loc, "The event `{0}' can only appear on the left hand side of += or -=", GetSignatureForError ()); else Report.Error (70, loc, "The event `{0}' can only appear on the left hand side of += or -= "+ "(except on the defining type)", Name); } + public override string GetSignatureForError () + { + return TypeManager.CSharpSignature (EventInfo); + } + public void EmitAddOrRemove (EmitContext ec, Expression source) { BinaryDelegate source_del = (BinaryDelegate) source; @@ -3751,10 +3861,10 @@ namespace Mono.CSharp { if (source_del.IsAddition) Invocation.EmitCall ( - ec, false, IsStatic, instance_expr, add_accessor, args, loc); + ec, false, IsStatic, InstanceExpression, add_accessor, args, loc); else Invocation.EmitCall ( - ec, false, IsStatic, instance_expr, remove_accessor, args, loc); + ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc); } } }