X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fecore.cs;h=743b255c62697aaa352b5ec0018ebccd130bb2b8;hb=9076dfdec8582c59a2c683da9943496514f8d2dd;hp=944c1e6bcba4bc1e2d8bb70866dd3430fde7dace;hpb=b53aaddb169dfbd0b3a365b7c05263cb7ff90e28;p=mono.git diff --git a/mcs/gmcs/ecore.cs b/mcs/gmcs/ecore.cs index 944c1e6bcba..743b255c626 100755 --- a/mcs/gmcs/ecore.cs +++ b/mcs/gmcs/ecore.cs @@ -61,7 +61,10 @@ namespace Mono.CSharp { // Disable control flow analysis while resolving the expression. // This is used when resolving the instance expression of a field expression. - DisableFlowAnalysis = 16 + DisableFlowAnalysis = 16, + + // Set if this is resolving the first part of a MemberAccess. + Intermediate = 32 } // @@ -92,6 +95,25 @@ 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 Type { + get; + } + } + /// /// This interface is implemented by variables /// @@ -184,22 +206,21 @@ namespace Mono.CSharp { /// /// Utility wrapper routine for Warning, just to beautify the code /// - public void Warning (int warning, string s) + public void Warning (int code, string format, params object[] args) { - if (!Location.IsNull (loc)) - Report.Warning (warning, loc, s); - else - Report.Warning (warning, s); + Report.Warning (code, loc, format, args); } /// - /// Utility wrapper routine for Warning, only prints the warning if - /// warnings of level `level' are enabled. + /// Tests presence of ObsoleteAttribute and report proper error /// - public void Warning (int warning, int level, string s) + protected void CheckObsoleteAttribute (Type type) { - if (level <= RootContext.WarningLevel) - Warning (warning, s); + ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type); + if (obsolete_attr == null) + return; + + AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, loc); } /// @@ -251,15 +272,9 @@ namespace Mono.CSharp { // value will be returned if the expression is not a type // reference // - public Expression ResolveAsTypeTerminal (EmitContext ec) + public TypeExpr ResolveAsTypeTerminal (EmitContext ec) { - Expression e = ResolveAsTypeStep (ec); - - if (e == null) - return null; - if (e is SimpleName) - return null; - return e; + return ResolveAsTypeStep (ec) as TypeExpr; } /// @@ -280,8 +295,10 @@ namespace Mono.CSharp { ec.DoFlowAnalysis = false; Expression e; + bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate; if (this is SimpleName) - e = ((SimpleName) this).DoResolveAllowStatic (ec); + e = ((SimpleName) this).DoResolveAllowStatic (ec, intermediate); + else e = DoResolve (ec); @@ -320,10 +337,12 @@ namespace Mono.CSharp { break; case ExprClass.MethodGroup: + if (!RootContext.V2){ if ((flags & ResolveFlags.MethodGroup) == 0) { ((MethodGroupExpr) e).ReportUsageError (); return null; } + } break; case ExprClass.Value: @@ -393,7 +412,7 @@ namespace Mono.CSharp { return null; } - if (e.type == null) + if ((e.type == null) && !(e is ConstructedType)) throw new Exception ("Expression " + e + " did not set its type after Resolve"); } @@ -411,6 +430,12 @@ namespace Mono.CSharp { /// public abstract void Emit (EmitContext ec); + public virtual void EmitBranchable (EmitContext ec, Label target, bool onTrue) + { + Emit (ec); + ec.ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + /// /// Protected constructor. Only derivate types should /// be able to be created @@ -464,7 +489,11 @@ namespace Mono.CSharp { else if (t == TypeManager.bool_type) return new BoolConstant ((bool) v); else if (TypeManager.IsEnumType (t)){ - Constant e = Constantify (v, TypeManager.TypeToCoreType (v.GetType ())); + Type real_type = TypeManager.TypeToCoreType (v.GetType ()); + if (real_type == t) + real_type = real_type.UnderlyingSystemType; + + Constant e = Constantify (v, real_type); return new EnumConstant (e, t); } else @@ -484,12 +513,15 @@ namespace Mono.CSharp { else if (mi is PropertyInfo) return new PropertyExpr (ec, (PropertyInfo) mi, loc); else if (mi is Type){ - return new TypeExpr ((System.Type) mi, loc); + return new TypeExpression ((System.Type) mi, loc); } return null; } + + private static ArrayList almostMatchedMembers = new ArrayList (4); + // // FIXME: Probably implement a cache for (t,name,current_access_set)? // @@ -534,8 +566,11 @@ namespace Mono.CSharp { string name, MemberTypes mt, BindingFlags bf, Location loc) { - MemberInfo [] mi = TypeManager.MemberLookup (container_type, qualifier_type, - queried_type, mt, bf, name); + almostMatchedMembers.Clear (); + + MemberInfo [] mi = TypeManager.MemberLookup ( + container_type, qualifier_type,queried_type, mt, bf, name, + almostMatchedMembers); if (mi == null) return null; @@ -592,7 +627,8 @@ namespace Mono.CSharp { /// find it. /// public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type, - Type queried_type, string name, Location loc) + Type queried_type, string name, + Location loc) { return MemberLookupFinal (ec, qualifier_type, queried_type, name, AllMemberTypes, AllBindingFlags, loc); @@ -610,26 +646,52 @@ namespace Mono.CSharp { e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc); - if (e != null) - return e; + 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); - // Error has already been reported. - if (errors < Report.Errors) - return null; - - MemberLookupFailed (ec, qualifier_type, queried_type, name, null, loc); - return null; + return e; } public static void MemberLookupFailed (EmitContext ec, Type qualifier_type, Type queried_type, string name, string class_name, Location loc) { - object lookup = TypeManager.MemberLookup (queried_type, null, queried_type, - AllMemberTypes, AllBindingFlags | - BindingFlags.NonPublic, name); + 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), + TypeManager.CSharpName (ec.ContainerType)); + return; + } + - if (lookup == null) { + 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 parent of the + // ec.ContainerType and the lookup succeeds with the latter one, + // then we are in this situation. + foreach (MemberInfo m in almostMatchedMembers) + 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; + } + almostMatchedMembers.Clear (); + } + + MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type, + AllMemberTypes, AllBindingFlags | + BindingFlags.NonPublic, name, null); + + if (mi == null) { if (class_name != null) Report.Error (103, loc, "The name `" + name + "' could not be " + "found in `" + class_name + "'"); @@ -640,39 +702,31 @@ namespace Mono.CSharp { return; } - if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) && - ec.ContainerType.IsSubclassOf (qualifier_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 parent of the - // ec.ContainerType and the lookup succeeds with the latter one, - // then we are in this situation. + 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]; - lookup = TypeManager.MemberLookup ( - ec.ContainerType, ec.ContainerType, ec.ContainerType, - AllMemberTypes, AllBindingFlags, name); - - if (lookup != null) { - Report.Error ( - 1540, loc, "Cannot access protected member `" + - TypeManager.CSharpName (qualifier_type) + "." + - name + "' " + "via a qualifier of type `" + - TypeManager.CSharpName (qualifier_type) + "'; the " + - "qualifier must be of type `" + - TypeManager.CSharpName (ec.ContainerType) + "' " + - "(or derived from it)"); + Report.Error (305, loc, + "Using the generic type `{0}' " + + "requires {1} type arguments", + TypeManager.GetFullName (t), + TypeManager.GetNumberOfTypeArguments (t)); return; } } + + if (qualifier_type != null) - Report.Error ( - 122, loc, "`" + TypeManager.CSharpName (qualifier_type) + "." + - name + "' is inaccessible due to its protection level"); - else - Report.Error ( - 122, loc, "`" + name + "' is inaccessible due to its " + - "protection level"); + Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", TypeManager.CSharpName (qualifier_type) + "." + name); + else if (name == ".ctor") { + Report.Error (143, loc, String.Format ("The type {0} has no constructors defined", + TypeManager.CSharpName (queried_type))); + } else { + Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", name); + } } static public MemberInfo GetFieldFromEvent (EventExpr event_expr) @@ -711,7 +765,8 @@ namespace Mono.CSharp { ArrayList arguments = new ArrayList (); arguments.Add (new Argument (e, Argument.AType.Expression)); - method = Invocation.OverloadResolve (ec, (MethodGroupExpr) operator_group, arguments, loc); + method = Invocation.OverloadResolve ( + ec, (MethodGroupExpr) operator_group, arguments, false, loc); if (method == null) return null; @@ -826,7 +881,7 @@ namespace Mono.CSharp { "a `" + sb.ToString () + "' was expected"); } - static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t) + 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)); @@ -1212,13 +1267,6 @@ namespace Mono.CSharp { return 0; } - // - // Default implementation of IAssignMethod.CacheTemporaries - // - public void CacheTemporaries (EmitContext ec) - { - } - static void Error_NegativeArrayIndex (Location loc) { Report.Error (284, loc, "Can not create array with a negative size"); @@ -1320,6 +1368,12 @@ namespace Mono.CSharp { public class EmptyCast : Expression { protected Expression child; + public Expression Child { + get { + return child; + } + } + public EmptyCast (Expression child, Type return_type) { eclass = child.eclass; @@ -1503,6 +1557,10 @@ namespace Mono.CSharp { { return Child.ConvertToInt (); } + + public override bool IsZeroInteger { + get { return Child.IsZeroInteger; } + } } /// @@ -1516,11 +1574,13 @@ namespace Mono.CSharp { public BoxedCast (Expression expr) : base (expr, TypeManager.object_type) { + eclass = ExprClass.Value; } public BoxedCast (Expression expr, Type target_type) : base (expr, target_type) { + eclass = ExprClass.Value; } public override Expression DoResolve (EmitContext ec) @@ -1559,9 +1619,13 @@ namespace Mono.CSharp { ILGenerator ig = ec.ig; base.Emit (ec); - ig.Emit (OpCodes.Unbox, t); + if (t.IsGenericParameter) + ig.Emit (OpCodes.Unbox_Any, t); + else { + ig.Emit (OpCodes.Unbox, t); - LoadFromPtr (ig, t); + LoadFromPtr (ig, t); + } } } @@ -1844,9 +1908,14 @@ namespace Mono.CSharp { { base.Emit (ec); - ec.ig.Emit (OpCodes.Castclass, type); - } - + if (child.Type.IsGenericParameter) + ec.ig.Emit (OpCodes.Box, child.Type); + + if (type.IsGenericParameter) + ec.ig.Emit (OpCodes.Unbox_Any, type); + else + ec.ig.Emit (OpCodes.Castclass, type); + } } /// @@ -1879,6 +1948,7 @@ namespace Mono.CSharp { /// public class SimpleName : Expression { public string Name; + public readonly TypeArguments Arguments; // // If true, then we are a simple name, not composed with a ". @@ -1899,6 +1969,14 @@ namespace Mono.CSharp { is_base = true; } + public SimpleName (string name, TypeArguments args, Location l) + { + Name = name; + Arguments = args; + loc = l; + is_base = true; + } + public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name) { if (ec.IsFieldInitializer) @@ -1933,26 +2011,26 @@ namespace Mono.CSharp { public override Expression DoResolve (EmitContext ec) { - return SimpleNameResolve (ec, null, false); + return SimpleNameResolve (ec, null, false, false); } public override Expression DoResolveLValue (EmitContext ec, Expression right_side) { - return SimpleNameResolve (ec, right_side, false); + return SimpleNameResolve (ec, right_side, false, false); } - public Expression DoResolveAllowStatic (EmitContext ec) + public Expression DoResolveAllowStatic (EmitContext ec, bool intermediate) { - return SimpleNameResolve (ec, null, true); + return SimpleNameResolve (ec, null, true, intermediate); } public override Expression ResolveAsTypeStep (EmitContext ec) { DeclSpace ds = ec.DeclSpace; NamespaceEntry ns = ds.NamespaceEntry; - Type t; - string alias_value; + TypeExpr t; + IAlias alias_value; // // Since we are cheating: we only do the Alias lookup for @@ -1963,53 +2041,81 @@ namespace Mono.CSharp { else alias_value = null; - if (ec.ResolvingTypeTree){ - if (alias_value != null){ - if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null) - return new TypeExpr (t, loc); - } + TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc); + if (generic_type != null) + return generic_type.ResolveAsTypeTerminal (ec); + if (ec.ResolvingTypeTree){ int errors = Report.Errors; - Type dt = ec.DeclSpace.FindType (loc, Name); + Type dt = ds.FindType (loc, Name); if (Report.Errors != errors) return null; if (dt != null) - return new TypeExpr (dt, loc); + return new TypeExpression (dt, loc); + + if (alias_value != null){ + if (alias_value.IsType) + return alias_value.Type; + if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null) + return t; + } } // // First, the using aliases // if (alias_value != null){ - if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null) - return new TypeExpr (t, loc); + if (alias_value.IsType) + return alias_value.Type; + if ((t = RootContext.LookupType (ds, alias_value.Name, true, loc)) != null) + return t; // we have alias value, but it isn't Type, so try if it's namespace - return new SimpleName (alias_value, loc); + return new SimpleName (alias_value.Name, loc); } - if (ec.IsGeneric){ - TypeParameterExpr generic_type = ds.LookupGeneric (Name, loc); - - if (generic_type != null) - return generic_type.ResolveAsTypeTerminal (ec); - } - // // Stage 2: Lookup up if we are an alias to a type // or a namespace. // if ((t = RootContext.LookupType (ds, Name, true, loc)) != null) - return new TypeExpr (t, loc); + return t; // No match, maybe our parent can compose us // into something meaningful. return this; } + Expression SimpleNameResolve (EmitContext ec, Expression right_side, + bool allow_static, bool intermediate) + { + Expression e = DoSimpleNameResolve (ec, right_side, allow_static, intermediate); + if (e == null) + return null; + + 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; + } + } + + if (e.Type != null && e.Type.IsPointer && !ec.InUnsafe) { + UnsafeError (loc); + return null; + } + + return e; + } + /// /// 7.5.2: Simple Names. /// @@ -2027,7 +2133,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 SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static) + Expression DoSimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static, bool intermediate) { Expression e = null; @@ -2094,13 +2200,16 @@ namespace Mono.CSharp { // NamespaceEntry ns = ec.DeclSpace.NamespaceEntry; if (is_base && ns != null){ - string alias_value = ns.LookupAlias (Name); + IAlias alias_value = ns.LookupAlias (Name); if (alias_value != null){ - Name = alias_value; + if (alias_value.IsType) + return alias_value.Type; + + Name = alias_value.Name; Type t; if ((t = TypeManager.LookupType (Name)) != null) - return new TypeExpr (t, loc); + return new TypeExpression (t, loc); // No match, maybe our parent can compose us // into something meaningful. @@ -2123,26 +2232,34 @@ namespace Mono.CSharp { if (me == null) return e; + if (Arguments != null) { + MethodGroupExpr mg = me as MethodGroupExpr; + if (mg == null) + return null; + + 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.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) && - !me.InstanceExpression.Type.IsSubclassOf (me.DeclaringType)) { + TypeManager.IsSubclassOrNestedChildOf (me.InstanceExpression.Type, me.DeclaringType) && + me.InstanceExpression.Type != me.DeclaringType && + !TypeManager.IsSubclassOf (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 + "'"); return null; } - if (right_side != null) - e = e.DoResolveLValue (ec, right_side); - else - e = e.DoResolve (ec); - - return e; + return (right_side != null) + ? e.DoResolveLValue (ec, right_side) + : e.DoResolve (ec); } if (ec.IsStatic || ec.IsFieldInitializer){ @@ -2175,22 +2292,20 @@ namespace Mono.CSharp { /// /// Fully resolved expression that evaluates to a type /// - public class TypeExpr : Expression { - public TypeExpr (Type t, Location l) + public abstract class TypeExpr : Expression, IAlias { + override public Expression ResolveAsTypeStep (EmitContext ec) { - Type = t; - eclass = ExprClass.Type; - loc = l; - } + TypeExpr t = DoResolveAsTypeStep (ec); + if (t == null) + return null; - public override Expression ResolveAsTypeStep (EmitContext ec) - { - return this; + eclass = ExprClass.Type; + return t; } override public Expression DoResolve (EmitContext ec) { - return this; + return ResolveAsTypeTerminal (ec); } override public void Emit (EmitContext ec) @@ -2198,9 +2313,119 @@ namespace Mono.CSharp { throw new Exception ("Should never be called"); } + public virtual bool CheckAccessLevel (DeclSpace ds) + { + return ds.CheckAccessLevel (Type); + } + + public virtual bool AsAccessible (DeclSpace ds, int flags) + { + return ds.AsAccessible (Type, flags); + } + + public virtual bool IsClass { + get { return Type.IsClass; } + } + + public virtual bool IsValueType { + get { return Type.IsValueType; } + } + + public virtual bool IsInterface { + get { return Type.IsInterface; } + } + + public virtual bool IsSealed { + get { return Type.IsSealed; } + } + + public virtual bool CanInheritFrom () + { + if (Type == TypeManager.enum_type || + (Type == TypeManager.value_type && RootContext.StdLib) || + Type == TypeManager.multicast_delegate_type || + Type == TypeManager.delegate_type || + Type == TypeManager.array_type) + return false; + + return true; + } + + public virtual bool IsAttribute { + get { + return Type == TypeManager.attribute_type || + Type.IsSubclassOf (TypeManager.attribute_type); + } + } + + public 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; + } + + public override bool Equals (object obj) + { + TypeExpr tobj = obj as TypeExpr; + if (tobj == null) + return false; + + return Type == tobj.Type; + } + + public override int GetHashCode () + { + return Type.GetHashCode (); + } + public override string ToString () { - return Type.ToString (); + return Name; + } + + bool IAlias.IsType { + get { return true; } + } + + TypeExpr IAlias.Type { + get { + return this; + } + } + } + + public class TypeExpression : TypeExpr, IAlias { + public TypeExpression (Type t, Location l) + { + Type = t; + eclass = ExprClass.Type; + loc = l; + } + + public override TypeExpr DoResolveAsTypeStep (EmitContext ec) + { + return this; + } + + public override string Name { + get { + return Type.ToString (); + } + } + + string IAlias.Name { + get { + return Type.FullName != null ? Type.FullName : Type.Name; + } } } @@ -2212,31 +2437,134 @@ namespace Mono.CSharp { public class TypeLookupExpression : TypeExpr { string name; - public TypeLookupExpression (string name) : base (null, Location.Null) + public TypeLookupExpression (string name) { this.name = name; } - public override Expression ResolveAsTypeStep (EmitContext ec) + public override TypeExpr DoResolveAsTypeStep (EmitContext ec) { - if (type == null) - type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null); + if (type == null) { + TypeExpr texpr = RootContext.LookupType ( + ec.DeclSpace, name, false, Location.Null); + if (texpr == null) + return null; + + type = texpr.ResolveType (ec); + if (type == null) + return null; + } + return this; } - public override Expression DoResolve (EmitContext ec) + public override string Name { + get { + return name; + } + } + } + + /// + /// Represents an "unbound generic type", ie. typeof (Foo<>). + /// See 14.5.11. + /// + public class UnboundTypeExpression : TypeLookupExpression { + public UnboundTypeExpression (string name) + : base (name) + { } + } + + public class TypeAliasExpression : TypeExpr, IAlias { + TypeExpr texpr; + TypeArguments args; + string name; + + public TypeAliasExpression (TypeExpr texpr, TypeArguments args, Location l) { - return ResolveAsTypeStep (ec); + this.texpr = texpr; + this.args = args; + loc = texpr.Location; + + eclass = ExprClass.Type; + if (args != null) + name = texpr.Name + "<" + args.ToString () + ">"; + else + name = texpr.Name; } - public override void Emit (EmitContext ec) + public override string Name { + get { return name; } + } + + public override TypeExpr DoResolveAsTypeStep (EmitContext ec) { - throw new Exception ("Should never be called"); + Type type = texpr.ResolveType (ec); + if (type == null) + return null; + + int num_args = TypeManager.GetNumberOfTypeArguments (type); + + if (args != null) { + if (num_args == 0) { + Report.Error (308, loc, + "The non-generic type `{0}' cannot " + + "be used with type arguments.", + TypeManager.CSharpName (type)); + return null; + } + + ConstructedType ctype = new ConstructedType (type, args, loc); + return ctype.ResolveAsTypeTerminal (ec); + } else if (num_args > 0) { + Report.Error (305, loc, + "Using the generic type `{0}' " + + "requires {1} type arguments", + TypeManager.GetFullName (type), num_args); + return null; + } + + return new TypeExpression (type, loc); } - public override string ToString () + public override Type ResolveType (EmitContext ec) { - return name; + TypeExpr t = ResolveAsTypeTerminal (ec); + if (t == null) + return null; + + type = t.ResolveType (ec); + return type; + } + + 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; } + } + + public override bool IsAttribute { + get { return texpr.IsAttribute; } } } @@ -2249,6 +2577,9 @@ namespace Mono.CSharp { 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; public MethodGroupExpr (MemberInfo [] mi, Location l) { @@ -2313,6 +2644,35 @@ namespace Mono.CSharp { } } + public bool HasTypeArguments { + get { + return has_type_arguments; + } + + set { + has_type_arguments = value; + } + } + + public bool IdenticalTypeName { + get { + return identical_type_name; + } + + set { + identical_type_name = value; + } + } + + public bool IsBase { + get { + return is_base; + } + set { + is_base = value; + } + } + public string Name { get { //return Methods [0].Name; @@ -2400,6 +2760,55 @@ namespace Mono.CSharp { { return RemoveMethods (false); } + + public Expression ResolveGeneric (EmitContext ec, TypeArguments args) + { + if (args.Resolve (ec) == false) + return null; + + Type[] atypes = args.Arguments; + + int first_count = 0; + MethodInfo first = null; + + ArrayList list = new ArrayList (); + foreach (MethodBase mb in Methods) { + MethodInfo mi = mb as MethodInfo; + if ((mi == null) || !mi.HasGenericParameters) + continue; + + Type[] gen_params = mi.GetGenericArguments (); + + if (first == null) { + first = mi; + first_count = gen_params.Length; + } + + if (gen_params.Length != atypes.Length) + continue; + + list.Add (mi.BindGenericParameters (atypes)); + } + + if (list.Count > 0) { + MethodGroupExpr new_mg = new MethodGroupExpr (list, Location); + new_mg.InstanceExpression = InstanceExpression; + new_mg.HasTypeArguments = true; + return new_mg; + } + + if (first != null) + Report.Error ( + 305, loc, "Using the generic method `{0}' " + + "requires {1} type arguments", Name, + first_count); + else + Report.Error ( + 308, loc, "The non-generic method `{0}' " + + "cannot be used with type arguments", Name); + + return null; + } } /// @@ -2410,11 +2819,15 @@ namespace Mono.CSharp { Expression instance_expr; VariableInfo variable_info; + LocalTemporary temp; + bool prepared; + bool is_field_initializer; + public FieldExpr (FieldInfo fi, Location l) { FieldInfo = fi; eclass = ExprClass.Variable; - type = fi.FieldType; + type = TypeManager.TypeToCoreType (fi.FieldType); loc = l; } @@ -2452,6 +2865,16 @@ namespace Mono.CSharp { } } + public bool IsFieldInitializer { + get { + return is_field_initializer; + } + + set { + is_field_initializer = value; + } + } + public VariableInfo VariableInfo { get { return variable_info; @@ -2479,6 +2902,19 @@ namespace Mono.CSharp { return null; } + ObsoleteAttribute oa; + FieldBase f = TypeManager.GetField (FieldInfo); + if (f != null) { + oa = f.GetObsoleteAttribute (ec.DeclSpace); + 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 the instance expression is a local variable or parameter. IVariable var = instance_expr as IVariable; if ((var == null) || (var.VariableInfo == null)) @@ -2528,7 +2964,7 @@ namespace Mono.CSharp { FieldBase fb = TypeManager.GetField (FieldInfo); if (fb != null) - fb.IsAssigned = true; + fb.SetAssigned (); // // InitOnly fields can only be assigned in constructors @@ -2538,7 +2974,14 @@ namespace Mono.CSharp { if (IsStatic && !ec.IsStatic) Report_AssignToReadonly (false); - if (ec.ContainerType == FieldInfo.DeclaringType) + Type ctype; + if (!is_field_initializer && + (ec.TypeContainer.CurrentType != null)) + ctype = ec.TypeContainer.CurrentType.ResolveType (ec); + else + ctype = ec.ContainerType; + + if (TypeManager.IsEqual (ctype, FieldInfo.DeclaringType)) return this; } @@ -2555,8 +2998,8 @@ namespace Mono.CSharp { return true; } - - override public void Emit (EmitContext ec) + + public void Emit (EmitContext ec, bool leave_copy) { ILGenerator ig = ec.ig; bool is_volatile = false; @@ -2576,66 +3019,52 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Volatile); ig.Emit (OpCodes.Ldsfld, FieldInfo); - return; - } - - if (instance_expr.Type.IsValueType){ - IMemoryLocation ml; - LocalTemporary tempo = null; - - if (!(instance_expr is IMemoryLocation)){ - tempo = new LocalTemporary (ec, instance_expr.Type); - - if (ec.RemapToProxy) - ec.EmitThis (); - - InstanceExpression.Emit (ec); - tempo.Store (ec); - ml = tempo; - } else - ml = (IMemoryLocation) instance_expr; - - ml.AddressOf (ec, AddressOp.Load); } else { - if (ec.RemapToProxy) - ec.EmitThis (); - else - instance_expr.Emit (ec); + if (!prepared) + EmitInstance (ec); + + if (is_volatile) + ig.Emit (OpCodes.Volatile); + + ig.Emit (OpCodes.Ldfld, FieldInfo); + } + + if (leave_copy) { + ec.ig.Emit (OpCodes.Dup); + if (!FieldInfo.IsStatic) { + temp = new LocalTemporary (ec, this.Type); + temp.Store (ec); + } } - if (is_volatile) - ig.Emit (OpCodes.Volatile); - - ig.Emit (OpCodes.Ldfld, FieldInfo); } - public void EmitAssign (EmitContext ec, Expression source) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { FieldAttributes fa = FieldInfo.Attributes; bool is_static = (fa & FieldAttributes.Static) != 0; bool is_readonly = (fa & FieldAttributes.InitOnly) != 0; ILGenerator ig = ec.ig; + prepared = prepare_for_load; if (is_readonly && !ec.IsConstructor){ Report_AssignToReadonly (!is_static); return; } - if (!is_static){ - Expression instance = instance_expr; - - if (instance.Type.IsValueType){ - IMemoryLocation ml = (IMemoryLocation) instance; - - ml.AddressOf (ec, AddressOp.Store); - } else { - if (ec.RemapToProxy) - ec.EmitThis (); - else - instance.Emit (ec); - } + if (!is_static) { + EmitInstance (ec); + if (prepare_for_load) + ig.Emit (OpCodes.Dup); } source.Emit (ec); + if (leave_copy) { + ec.ig.Emit (OpCodes.Dup); + if (!FieldInfo.IsStatic) { + temp = new LocalTemporary (ec, this.Type); + temp.Store (ec); + } + } if (FieldInfo is FieldBuilder){ FieldBase f = TypeManager.GetField (FieldInfo); @@ -2651,6 +3080,29 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Stsfld, FieldInfo); else ig.Emit (OpCodes.Stfld, FieldInfo); + + if (temp != null) + 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); } public void AddressOf (EmitContext ec, AddressOp mode) @@ -2676,9 +3128,21 @@ namespace Mono.CSharp { // Handle initonly fields specially: make a copy and then // get the address of the copy. // - if (FieldInfo.IsInitOnly && !ec.IsConstructor){ + bool need_copy; + if (FieldInfo.IsInitOnly){ + need_copy = true; + if (ec.IsConstructor){ + if (FieldInfo.IsStatic){ + if (ec.IsStatic) + need_copy = false; + } else + need_copy = false; + } + } else + need_copy = false; + + if (need_copy){ LocalBuilder local; - Emit (ec); local = ig.DeclareLocal (type); ig.Emit (OpCodes.Stloc, local); @@ -2686,22 +3150,11 @@ namespace Mono.CSharp { return; } - if (FieldInfo.IsStatic) - ig.Emit (OpCodes.Ldsflda, FieldInfo); - else { - // - // In the case of `This', we call the AddressOf method, which will - // only load the pointer, and not perform an Ldobj immediately after - // the value has been loaded into the stack. - // - if (instance_expr is This) - ((This)instance_expr).AddressOf (ec, AddressOp.LoadStore); - else if (instance_expr.Type.IsValueType && instance_expr is IMemoryLocation){ - IMemoryLocation ml = (IMemoryLocation) instance_expr; - ml.AddressOf (ec, AddressOp.LoadStore); - } else - instance_expr.Emit (ec); + if (FieldInfo.IsStatic){ + ig.Emit (OpCodes.Ldsflda, FieldInfo); + } else { + EmitInstance (ec); ig.Emit (OpCodes.Ldflda, FieldInfo); } } @@ -2740,6 +3193,8 @@ namespace Mono.CSharp { bool must_do_cs1540_check; Expression instance_expr; + LocalTemporary temp; + bool prepared; public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l) { @@ -2802,77 +3257,104 @@ namespace Mono.CSharp { return true; } - MethodInfo GetAccessor (Type invocation_type, string accessor_name) + MethodInfo FindAccessor (Type invocation_type, bool is_set) { BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Static | BindingFlags.Instance; - MemberInfo[] group; + BindingFlags.Static | BindingFlags.Instance | + BindingFlags.DeclaredOnly; - group = TypeManager.MemberLookup ( - invocation_type, invocation_type, PropertyInfo.DeclaringType, - MemberTypes.Method, flags, accessor_name + "_" + PropertyInfo.Name); + Type current = PropertyInfo.DeclaringType; + for (; current != null; current = current.BaseType) { + MemberInfo[] group = TypeManager.MemberLookup ( + invocation_type, invocation_type, current, + MemberTypes.Property, flags, PropertyInfo.Name, null); - // - // The first method is the closest to us - // - if (group == null) + if (group == null) + continue; + + if (group.Length != 1) + // Oooops, can this ever happen ? + return null; + + PropertyInfo pi = (PropertyInfo) group [0]; + + MethodInfo get = pi.GetGetMethod (true); + MethodInfo set = pi.GetSetMethod (true); + + if (is_set) { + if (set != null) + return set; + } else { + if (get != null) + return get; + } + + MethodInfo accessor = get != null ? get : set; + if (accessor == null) + continue; + if ((accessor.Attributes & MethodAttributes.NewSlot) != 0) + break; + } + + return null; + } + + MethodInfo GetAccessor (Type invocation_type, bool is_set) + { + MethodInfo mi = FindAccessor (invocation_type, is_set); + if (mi == null) return null; - foreach (MethodInfo mi in group) { - MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask; + MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask; - // - // If only accessible to the current class or children - // - if (ma == MethodAttributes.Private) { - Type declaring_type = mi.DeclaringType; + // + // If only accessible to the current class or children + // + if (ma == MethodAttributes.Private) { + Type declaring_type = mi.DeclaringType; - if (invocation_type != declaring_type){ - if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType)) - return mi; - else - continue; - } else + if (invocation_type != declaring_type){ + if (TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType)) return mi; - } - // - // FamAndAssem requires that we not only derivate, but we are on the - // same assembly. - // - if (ma == MethodAttributes.FamANDAssem){ - if (mi.DeclaringType.Assembly != invocation_type.Assembly) - continue; else - return mi; - } + return null; + } else + return mi; + } + // + // FamAndAssem requires that we not only derivate, but we are on the + // same assembly. + // + if (ma == MethodAttributes.FamANDAssem){ + if (mi.DeclaringType.Assembly != invocation_type.Assembly) + return null; + else + return mi; + } - // 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) - continue; - else - return mi; - } + // 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) + return mi; + } - // We already know that we aren't in the same assembly. - if (ma == MethodAttributes.Assembly) - continue; + // We already know that we aren't in the same assembly. + if (ma == MethodAttributes.Assembly) + return null; - // Family and FamANDAssem require that we derive. - if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){ - if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType)) - continue; - else { + // Family and FamANDAssem require that we derive. + if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem) || (ma == MethodAttributes.FamORAssem)){ + if (!TypeManager.IsSubclassOrNestedChildOf (invocation_type, mi.DeclaringType)) + return null; + else { + if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType)) must_do_cs1540_check = true; - return mi; - } + return mi; } - - return mi; } - return null; + return mi; } // @@ -2881,18 +3363,16 @@ namespace Mono.CSharp { // void ResolveAccessors (EmitContext ec) { - getter = GetAccessor (ec.ContainerType, "get"); + getter = GetAccessor (ec.ContainerType, false); if ((getter != null) && getter.IsStatic) is_static = true; - setter = GetAccessor (ec.ContainerType, "set"); + setter = GetAccessor (ec.ContainerType, true); if ((setter != null) && setter.IsStatic) is_static = true; if (setter == null && getter == null){ - Error (122, "`" + PropertyInfo.Name + "' " + - "is inaccessible because of its protection level"); - + Report.Error (122, loc, "'{0}' is inaccessible due to its protection level", PropertyInfo.Name); } } @@ -2928,6 +3408,16 @@ namespace Mono.CSharp { override public Expression DoResolve (EmitContext ec) { + if (getter != null){ + if (TypeManager.GetArgumentTypes (getter).Length != 0){ + Report.Error ( + 117, loc, "`{0}' does not contain a " + + "definition for `{1}'.", getter.DeclaringType, + Name); + return null; + } + } + if (getter == null){ // // The following condition happens if the PropertyExpr was @@ -2979,6 +3469,14 @@ namespace Mono.CSharp { return null; } + if (TypeManager.GetArgumentTypes (setter).Length != 1){ + Report.Error ( + 117, loc, "`{0}' does not contain a " + + "definition for `{1}'.", getter.DeclaringType, + Name); + return null; + } + if (!InstanceResolve (ec)) return null; @@ -2990,11 +3488,53 @@ namespace Mono.CSharp { PropertyInfo.DeclaringType + "." +PropertyInfo.Name); 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."); + return null; + } + return this; } - override public void Emit (EmitContext ec) + + + 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); + // // Special case: length of single dimension array property is turned into ldlen // @@ -3006,27 +3546,50 @@ namespace Mono.CSharp { // System.Array.Length can be called, but the Type does not // support invoking GetArrayRank, so test for that case first // - if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){ - instance_expr.Emit (ec); + if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)) { ec.ig.Emit (OpCodes.Ldlen); + ec.ig.Emit (OpCodes.Conv_I4); return; } } - Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, loc); + Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), getter, null, loc); + + if (!leave_copy) + return; + ec.ig.Emit (OpCodes.Dup); + if (!is_static) { + temp = new LocalTemporary (ec, this.Type); + temp.Store (ec); + } } // // Implements the IAssignMethod interface for assignments // - public void EmitAssign (EmitContext ec, Expression source) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) { - Argument arg = new Argument (source, Argument.AType.Expression); - ArrayList args = new ArrayList (); + prepared = prepare_for_load; + + EmitInstance (ec); - args.Add (arg); - Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, loc); + source.Emit (ec); + if (leave_copy) { + ec.ig.Emit (OpCodes.Dup); + if (!is_static) { + temp = new LocalTemporary (ec, this.Type); + temp.Store (ec); + } + } + + ArrayList args = new ArrayList (1); + args.Add (new Argument (new EmptyAddressOf (), Argument.AType.Expression)); + + Invocation.EmitCall (ec, IsBase, IsStatic, new EmptyAddressOf (), setter, args, loc); + + if (temp != null) + temp.Emit (ec); } override public void EmitStatement (EmitContext ec) @@ -3041,7 +3604,7 @@ namespace Mono.CSharp { /// public class EventExpr : Expression, IMemberExpr { public readonly EventInfo EventInfo; - public Expression instance_expr; + Expression instance_expr; bool is_static; MethodInfo add_accessor, remove_accessor;