X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fmethod.cs;h=a5d7bb24a8a41a736800a454dd89cb965d68e7fb;hb=d1cf2f5de8a032f4e6dde6f2a58cae55ba8eccb5;hp=6bf279f613309b23fee1835ea6ba7fc6997d6c0b;hpb=dccbaddcf2a84c98a987d92a820c65cb0131894a;p=mono.git diff --git a/mcs/mcs/method.cs b/mcs/mcs/method.cs index 6bf279f6133..a5d7bb24a8a 100644 --- a/mcs/mcs/method.cs +++ b/mcs/mcs/method.cs @@ -13,10 +13,6 @@ using System; using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; @@ -28,6 +24,18 @@ using XmlElement = System.Object; using System.Xml; #endif +#if STATIC +using MetaType = IKVM.Reflection.Type; +using SecurityType = System.Collections.Generic.List; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + using Mono.CompilerServices.SymbolWriter; namespace Mono.CSharp { @@ -46,6 +54,12 @@ namespace Mono.CSharp { this.parameters = parameters; } + public override Variance ExpectedMemberTypeVariance { + get { + return Variance.Covariant; + } + } + // // Returns the System.Type array for the parameters of this method // @@ -113,32 +127,20 @@ namespace Mono.CSharp { } // - // Returns a string that represents the signature for this - // member which should be used in XML documentation. + // Represents header string for documentation comment. // - public override string GetDocCommentName (DeclSpace ds) + public override string DocCommentHeader { - return DocUtil.GetMethodDocCommentName (this, parameters, ds); + get { return "M:"; } } - // - // Raised (and passed an XmlElement that contains the comment) - // when GenerateDocComment is writing documentation expectedly. - // - // FIXME: with a few effort, it could be done with XmlReader, - // that means removal of DOM use. - // - internal override void OnGenerateDocComment (XmlElement el) + public override void Emit () { - DocUtil.OnMethodGenerateDocComment (this, el, Report); - } + if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + parameters.CheckConstraints (this); + } - // - // Represents header string for documentation comment. - // - public override string DocCommentHeader - { - get { return "M:"; } + base.Emit (); } public override bool EnableOverloadChecks (MemberCore overload) @@ -154,6 +156,15 @@ namespace Mono.CSharp { return base.EnableOverloadChecks (overload); } + public override string GetSignatureForDocumentation () + { + string s = base.GetSignatureForDocumentation (); + if (MemberName.Arity > 0) + s += "``" + MemberName.Arity.ToString (); + + return s + parameters.GetSignatureForDocumentation (); + } + public MethodSpec Spec { get { return spec; } } @@ -185,9 +196,9 @@ namespace Mono.CSharp { // MethodInfo MakeGenericMethod (TypeSpec[] targs); } - public class MethodSpec : MemberSpec, IParametersMember + public sealed class MethodSpec : MemberSpec, IParametersMember { - MethodBase metaInfo; + MethodBase metaInfo, inflatedMetaInfo; AParametersCollection parameters; TypeSpec returnType; @@ -293,25 +304,76 @@ namespace Mono.CSharp { public MethodBase GetMetaInfo () { - if ((state & StateFlags.PendingMetaInflate) != 0) { - if (DeclaringType.IsTypeBuilder) { - if (IsConstructor) - metaInfo = TypeBuilder.GetConstructor (DeclaringType.GetMetaInfo (), (ConstructorInfo) metaInfo); - else - metaInfo = TypeBuilder.GetMethod (DeclaringType.GetMetaInfo (), (MethodInfo) metaInfo); + // + // inflatedMetaInfo is extra field needed for cases where we + // inflate method but another nested type can later inflate + // again (the cache would be build with inflated metaInfo) and + // TypeBuilder can work with method definitions only + // + if (inflatedMetaInfo == null) { + if ((state & StateFlags.PendingMetaInflate) != 0) { + var dt_meta = DeclaringType.GetMetaInfo (); + + if (DeclaringType.IsTypeBuilder) { + if (IsConstructor) + inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) metaInfo); + else + inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) metaInfo); + } else { +#if STATIC + // it should not be reached + throw new NotImplementedException (); +#else + inflatedMetaInfo = MethodInfo.GetMethodFromHandle (metaInfo.MethodHandle, dt_meta.TypeHandle); +#endif + } + + state &= ~StateFlags.PendingMetaInflate; } else { - metaInfo = MethodInfo.GetMethodFromHandle (metaInfo.MethodHandle, DeclaringType.GetMetaInfo ().TypeHandle); + inflatedMetaInfo = metaInfo; } - - state &= ~StateFlags.PendingMetaInflate; } if ((state & StateFlags.PendingMakeMethod) != 0) { - metaInfo = ((MethodInfo) metaInfo).MakeGenericMethod (targs.Select (l => l.GetMetaInfo ()).ToArray ()); + var sre_targs = new MetaType[targs.Length]; + for (int i = 0; i < sre_targs.Length; ++i) + sre_targs[i] = targs[i].GetMetaInfo (); + + inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs); state &= ~StateFlags.PendingMakeMethod; } - return metaInfo; + return inflatedMetaInfo; + } + + public override string GetSignatureForDocumentation () + { + string name; + switch (Kind) { + case MemberKind.Constructor: + name = "#ctor"; + break; + case MemberKind.Method: + if (Arity > 0) + name = Name + "``" + Arity.ToString (); + else + name = Name; + + break; + default: + name = Name; + break; + } + + name = DeclaringType.GetSignatureForDocumentation () + "." + name + parameters.GetSignatureForDocumentation (); + if (Kind == MemberKind.Operator) { + var op = Operator.GetType (Name).Value; + if (op == Operator.OpType.Explicit || op == Operator.OpType.Implicit) { + name += "~" + ReturnType.GetSignatureForDocumentation (); + } + } + + return name; } public override string GetSignatureForError () @@ -354,15 +416,16 @@ namespace Mono.CSharp { public override MemberSpec InflateMember (TypeParameterInflator inflator) { var ms = (MethodSpec) base.InflateMember (inflator); + ms.inflatedMetaInfo = null; ms.returnType = inflator.Inflate (returnType); ms.parameters = parameters.Inflate (inflator); if (IsGeneric) - ms.constraints = TypeParameterSpec.InflateConstraints (inflator, GenericDefinition.TypeParameters); + ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints); return ms; } - public MethodSpec MakeGenericMethod (params TypeSpec[] targs) + public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs) { if (targs == null) throw new ArgumentNullException (); @@ -373,7 +436,7 @@ namespace Mono.CSharp { //if (generic_intances == null) // generic_intances = new Dictionary (TypeSpecArrayComparer.Default); - var inflator = new TypeParameterInflator (DeclaringType, GenericDefinition.TypeParameters, targs); + var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs); var inflated = (MethodSpec) MemberwiseClone (); inflated.declaringType = inflator.TypeInstance; @@ -406,9 +469,7 @@ namespace Mono.CSharp { var ms = (MethodSpec) MemberwiseClone (); if (decl != DeclaringType) { - // Gets back MethodInfo in case of metaInfo was inflated - ms.metaInfo = MemberCache.GetMember (DeclaringType.GetDefinition (), this).metaInfo; - + ms.inflatedMetaInfo = null; ms.declaringType = decl; ms.state |= StateFlags.PendingMetaInflate; } @@ -421,6 +482,23 @@ namespace Mono.CSharp { return ms; } + public override List ResolveMissingDependencies () + { + var missing = returnType.ResolveMissingDependencies (); + foreach (var pt in parameters.Types) { + var m = pt.GetMissingDependencies (); + if (m == null) + continue; + + if (missing == null) + missing = new List (); + + missing.AddRange (m); + } + + return missing; + } + public void SetMetaInfo (MethodInfo info) { if (this.metaInfo != null) @@ -434,10 +512,10 @@ namespace Mono.CSharp { { public MethodBuilder MethodBuilder; ReturnParameter return_attributes; - Dictionary declarative_security; + SecurityType declarative_security; protected MethodData MethodData; - static string[] attribute_targets = new string [] { "method", "return" }; + static readonly string[] attribute_targets = new string [] { "method", "return" }; protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, @@ -457,8 +535,8 @@ namespace Mono.CSharp { return; } - if (a.IsInternalMethodImplAttribute) { - is_external_implementation = true; + if (a.Type == pa.MethodImpl) { + is_external_implementation = a.IsInternalCall (); } if (a.Type == pa.DllImport) { @@ -470,9 +548,7 @@ namespace Mono.CSharp { } if (a.IsValidSecurityAttribute ()) { - if (declarative_security == null) - declarative_security = new Dictionary (); - a.ExtractSecurityPermissionSet (declarative_security); + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); return; } @@ -576,23 +652,16 @@ namespace Mono.CSharp { public override void Emit () { if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) - PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (MethodBuilder); + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder); if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) - PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (MethodBuilder); + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder); - if (ReturnType == InternalType.Dynamic) { + if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { return_attributes = new ReturnParameter (this, MethodBuilder, Location); - PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder); - } else { - var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType); - if (trans_flags != null) { - var pa = PredefinedAttributes.Get.DynamicTransform; - if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) { - return_attributes = new ReturnParameter (this, MethodBuilder, Location); - return_attributes.Builder.SetCustomAttribute ( - new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags })); - } - } + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.HasDynamicElement) { + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location); } if (OptAttributes != null) @@ -600,15 +669,22 @@ namespace Mono.CSharp { if (declarative_security != null) { foreach (var de in declarative_security) { +#if STATIC + MethodBuilder.__AddDeclarativeSecurity (de); +#else MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif } } - if (MethodData != null) - MethodData.Emit (Parent); + if (type_expr != null) + ConstraintChecker.Check (this, member_type, type_expr.Location); base.Emit (); + if (MethodData != null) + MethodData.Emit (Parent); + Block = null; MethodData = null; } @@ -640,6 +716,12 @@ namespace Mono.CSharp { #region IMethodData Members + bool IMethodData.IsAccessor { + get { + return false; + } + } + public TypeSpec ReturnType { get { return MemberType; @@ -670,7 +752,7 @@ namespace Mono.CSharp { if (OptAttributes == null) return null; - Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional); + Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional); if (attrs == null) return null; @@ -718,12 +800,17 @@ namespace Mono.CSharp { public int Token { get { - if (method is MethodBuilder) - return ((MethodBuilder) method).GetToken ().Token; - else if (method is ConstructorBuilder) - return ((ConstructorBuilder) method).GetToken ().Token; + MethodToken token; + var mb = method as MethodBuilder; + if (mb != null) + token = mb.GetToken (); else - throw new NotSupportedException (); + token = ((ConstructorBuilder) method).GetToken (); +#if STATIC + if (token.IsPseudoToken) + return ((ModuleBuilder) method.Module).ResolvePseudoToken (token.Token); +#endif + return token.Token; } } @@ -759,33 +846,15 @@ namespace Mono.CSharp { public class Method : MethodOrOperator, IGenericMethodDefinition { - /// - /// Modifiers allowed in a class declaration - /// - const Modifiers AllowedModifiers = - Modifiers.NEW | - Modifiers.PUBLIC | - Modifiers.PROTECTED | - Modifiers.INTERNAL | - Modifiers.PRIVATE | - Modifiers.STATIC | - Modifiers.VIRTUAL | - Modifiers.SEALED | - Modifiers.OVERRIDE | - Modifiers.ABSTRACT | - Modifiers.UNSAFE | - Modifiers.EXTERN; - - const Modifiers AllowedInterfaceModifiers = - Modifiers.NEW | Modifiers.UNSAFE; - Method partialMethodImplementation; public Method (DeclSpace parent, GenericMethod generic, FullNamedExpression return_type, Modifiers mod, MemberName name, ParametersCompiled parameters, Attributes attrs) : base (parent, generic, return_type, mod, - parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct : + AllowedModifiersClass, name, attrs, parameters) { } @@ -796,7 +865,7 @@ namespace Mono.CSharp { { } -#region Properties + #region Properties public override TypeParameter[] CurrentTypeParameters { get { @@ -807,25 +876,9 @@ namespace Mono.CSharp { } } - public override bool HasUnresolvedConstraints { - get { - if (CurrentTypeParameters == null) - return false; - - // When overriding base method constraints are fetched from - // base method but to find it we have to resolve parameters - // to find exact base method match - if (IsExplicitImpl || (ModFlags & Modifiers.OVERRIDE) != 0) - return base_method == null; - - // Even for non-override generic method constraints check has to be - // delayed after all constraints are resolved - return true; - } - } - public TypeParameterSpec[] TypeParameters { get { + // TODO: Cache this return CurrentTypeParameters.Select (l => l.Type).ToArray (); } } @@ -847,13 +900,12 @@ namespace Mono.CSharp { { Report.Error (17, b.Location, "Program `{0}' has more than one entry point defined: `{1}'", - CodeGen.FileName, b.GetSignatureForError ()); + b.Module.Builder.ScopeName, b.GetSignatureForError ()); } bool IsEntryPoint () { - if (ReturnType != TypeManager.void_type && - ReturnType != TypeManager.int32_type) + if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int) return false; if (parameters.IsEmpty) @@ -863,11 +915,11 @@ namespace Mono.CSharp { return false; var ac = parameters.Types [0] as ArrayContainer; - return ac != null && ac.Rank == 1 && ac.Element == TypeManager.string_type && + return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String && (parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE; } - public override FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104) + public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) { if (arity == 0) { TypeParameter[] tp = CurrentTypeParameters; @@ -878,7 +930,7 @@ namespace Mono.CSharp { } } - return base.LookupNamespaceOrType (name, arity, loc, ignore_cs0104); + return base.LookupNamespaceOrType (name, arity, mode, loc); } public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) @@ -889,13 +941,13 @@ namespace Mono.CSharp { return; } - if (ReturnType != TypeManager.void_type) { - Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ()); + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ()); return; } - if ((ModFlags & Modifiers.OVERRIDE) != 0) { - Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ()); + if (ReturnType.Kind != MemberKind.Void) { + Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ()); return; } @@ -937,9 +989,43 @@ namespace Mono.CSharp { if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) { if (base_method != null) { base_tparams = base_method.GenericDefinition.TypeParameters; + if (base_method.DeclaringType.IsGeneric) { base_decl_tparams = base_method.DeclaringType.MemberDefinition.TypeParameters; - base_targs = Parent.BaseType.TypeArguments; + + var base_type_parent = CurrentType; + while (base_type_parent.BaseType != base_method.DeclaringType) { + base_type_parent = base_type_parent.BaseType; + } + + base_targs = base_type_parent.BaseType.TypeArguments; + } + + if (base_method.IsGeneric) { + ObsoleteAttribute oa; + foreach (var base_tp in base_tparams) { + oa = base_tp.BaseType.GetAttributeObsolete (); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, base_tp.BaseType.GetSignatureForError (), Location, Report); + } + + if (base_tp.InterfacesDefined != null) { + foreach (var iface in base_tp.InterfacesDefined) { + oa = iface.GetAttributeObsolete (); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, iface.GetSignatureForError (), Location, Report); + } + } + } + } + + if (base_decl_tparams.Length != 0) { + base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray (); + base_targs = base_targs.Concat (tparams.Select (l => l.Type)).ToArray (); + } else { + base_decl_tparams = base_tparams; + base_targs = tparams.Select (l => l.Type).ToArray (); + } } } else if (MethodData.implementing != null) { base_tparams = MethodData.implementing.GenericDefinition.TypeParameters; @@ -966,11 +1052,38 @@ namespace Mono.CSharp { // if (base_tparams != null) { var base_tparam = base_tparams[i]; - tp.Type.SpecialConstraint = base_tparam.SpecialConstraint; + var local_tparam = tp.Type; + local_tparam.SpecialConstraint = base_tparam.SpecialConstraint; - var inflator = new TypeParameterInflator (CurrentType, base_decl_tparams, base_targs); - base_tparam.InflateConstraints (inflator, tp.Type); - } else if (MethodData.implementing != null) { + var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs); + base_tparam.InflateConstraints (inflator, local_tparam); + + // + // Check all type argument constraints for possible collision + // introduced by inflating inherited constraints in this context + // + // Conflict example: + // + // class A { virtual void Foo () where U : class, T {} } + // class B : A { override void Foo {} } + // + var local_tparam_targs = local_tparam.TypeArguments; + if (local_tparam_targs != null) { + for (int ii = 0; ii < local_tparam_targs.Length; ++ii) { + var ta = local_tparam_targs [ii]; + if (!ta.IsClass && !ta.IsStruct) + continue; + + if (Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location)) { + local_tparam.ChangeTypeArgumentToBaseType (ii); + } + } + } + + continue; + } + + if (MethodData.implementing != null) { var base_tp = MethodData.implementing.Constraints[i]; if (!tp.Type.HasSameConstraintsImplementation (base_tp)) { Report.SymbolRelatedToPreviousError (MethodData.implementing); @@ -987,24 +1100,25 @@ namespace Mono.CSharp { // public override bool Define () { - if (type_expr.Type == TypeManager.void_type && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) { - Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?"); - } - if (!base.Define ()) return false; + if (member_type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) { + Report.Warning (465, 1, Location, + "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?"); + } + if (partialMethodImplementation != null && IsPartialDefinition) MethodBuilder = partialMethodImplementation.MethodBuilder; - if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) { + if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) { Error1599 (Location, ReturnType, Report); return false; } if (CurrentTypeParameters == null) { if (base_method != null) { - if (parameters.Count == 1 && ParameterTypes[0] == TypeManager.object_type && Name == "Equals") + if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && Name == "Equals") Parent.PartialContainer.Mark_HasEquals (); else if (parameters.IsEmpty && Name == "GetHashCode") Parent.PartialContainer.Mark_HasGetHashCode (); @@ -1014,12 +1128,12 @@ namespace Mono.CSharp { DefineTypeParameters (); } - if (block != null && block.IsIterator && !(Parent is IteratorStorey)) { + if (block != null && block.IsIterator) { // // Current method is turned into automatically generated // wrapper which creates an instance of iterator // - Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler); + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); ModFlags |= Modifiers.DEBUGGER_HIDDEN; } @@ -1032,7 +1146,7 @@ namespace Mono.CSharp { Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class", GetSignatureForError ()); - PredefinedAttribute pa = PredefinedAttributes.Get.Extension; + PredefinedAttribute pa = Module.PredefinedAttributes.Extension; if (!pa.IsDefined) { Report.Error (1110, Location, "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter", @@ -1042,7 +1156,7 @@ namespace Mono.CSharp { ModFlags |= Modifiers.METHOD_EXTENSION; Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION; Spec.DeclaringType.SetExtensionMethodContainer (); - CodeGen.Assembly.HasExtensionMethods = true; + Parent.Module.HasExtensionMethod = true; } else { Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class", GetSignatureForError ()); @@ -1052,22 +1166,19 @@ namespace Mono.CSharp { // // This is used to track the Entry Point, // - if (RootContext.NeedsEntryPoint && - Name == "Main" && - (RootContext.MainClass == null || - RootContext.MainClass == Parent.TypeBuilder.FullName)){ + var settings = Compiler.Settings; + if (settings.NeedsEntryPoint && Name == "Main" && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) { if (IsEntryPoint ()) { - - if (RootContext.EntryPoint == null) { + if (Parent.DeclaringAssembly.EntryPoint == null) { if (Parent.IsGeneric || MemberName.IsGeneric) { Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type", GetSignatureForError ()); } else { SetIsUsed (); - RootContext.EntryPoint = this; + Parent.DeclaringAssembly.EntryPoint = this; } } else { - Error_DuplicateEntryPoint (RootContext.EntryPoint); + Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint); Error_DuplicateEntryPoint (this); } } else { @@ -1085,34 +1196,26 @@ namespace Mono.CSharp { public override void Emit () { try { - Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData); if (IsPartialDefinition) { // // Use partial method implementation builder for partial method declaration attributes // if (partialMethodImplementation != null) { MethodBuilder = partialMethodImplementation.MethodBuilder; - return; } - } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) { + + return; + } + + if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) { Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration", GetSignatureForError ()); } if (CurrentTypeParameters != null) { - var ge = type_expr as GenericTypeExpr; - if (ge != null) - ge.CheckConstraints (this); - - foreach (Parameter p in parameters.FixedParameters) { - ge = p.TypeExpression as GenericTypeExpr; - if (ge != null) - ge.CheckConstraints (this); - } - for (int i = 0; i < CurrentTypeParameters.Length; ++i) { var tp = CurrentTypeParameters [i]; - tp.CheckGenericConstraints (); + tp.CheckGenericConstraints (false); tp.Emit (); } } @@ -1120,7 +1223,7 @@ namespace Mono.CSharp { base.Emit (); if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0) - PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder); + Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder); } catch { Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}", Location, MethodBuilder); @@ -1207,47 +1310,46 @@ namespace Mono.CSharp { // FIXME: Hack var caller_builder = (Constructor) ec.MemberContext; - if (argument_list != null) { - bool dynamic; - - // - // Spec mandates that constructor initializer will not have `this' access - // - using (ec.Set (ResolveContext.Options.BaseInitializer)) { + // + // Spec mandates that constructor initializer will not have `this' access + // + using (ec.Set (ResolveContext.Options.BaseInitializer)) { + if (argument_list != null) { + bool dynamic; argument_list.Resolve (ec, out dynamic); - } - if (dynamic) { - ec.Report.Error (1975, loc, - "The constructor call cannot be dynamically dispatched within constructor initializer"); + if (dynamic) { + ec.Report.Error (1975, loc, + "The constructor call cannot be dynamically dispatched within constructor initializer"); - return null; + return null; + } } - } - type = ec.CurrentType; - if (this is ConstructorBaseInitializer) { - if (ec.CurrentType.BaseType == null) - return this; + type = ec.CurrentType; + if (this is ConstructorBaseInitializer) { + if (ec.CurrentType.BaseType == null) + return this; - type = ec.CurrentType.BaseType; - if (ec.CurrentType.IsStruct) { - ec.Report.Error (522, loc, - "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); - return this; + type = ec.CurrentType.BaseType; + if (ec.CurrentType.IsStruct) { + ec.Report.Error (522, loc, + "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); + return this; + } + } else { + // + // It is legal to have "this" initializers that take no arguments + // in structs, they are just no-ops. + // + // struct D { public D (int a) : this () {} + // + if (ec.CurrentType.IsStruct && argument_list == null) + return this; } - } else { - // - // It is legal to have "this" initializers that take no arguments - // in structs, they are just no-ops. - // - // struct D { public D (int a) : this () {} - // - if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null) - return this; - } - base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); + base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); + } // TODO MemberCache: Does it work for inflated types ? if (base_ctor == caller_builder.Spec){ @@ -1299,7 +1401,7 @@ namespace Mono.CSharp { public class Constructor : MethodCore, IMethodData { public ConstructorBuilder ConstructorBuilder; public ConstructorInitializer Initializer; - Dictionary declarative_security; + SecurityType declarative_security; bool has_compliant_args; // @@ -1316,6 +1418,9 @@ namespace Mono.CSharp { static readonly string[] attribute_targets = new string [] { "method" }; + public static readonly string ConstructorName = ".ctor"; + public static readonly string TypeConstructorName = ".cctor"; + // // The spec claims that static is not permitted, but // my very own code has static constructors. @@ -1333,7 +1438,15 @@ namespace Mono.CSharp { } public override AttributeTargets AttributeTargets { - get { return AttributeTargets.Constructor; } + get { + return AttributeTargets.Constructor; + } + } + + bool IMethodData.IsAccessor { + get { + return false; + } } // @@ -1352,15 +1465,12 @@ namespace Mono.CSharp { public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) { if (a.IsValidSecurityAttribute ()) { - if (declarative_security == null) { - declarative_security = new Dictionary (); - } - a.ExtractSecurityPermissionSet (declarative_security); + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); return; } - if (a.IsInternalMethodImplAttribute) { - is_external_implementation = true; + if (a.Type == pa.MethodImpl) { + is_external_implementation = a.IsInternalCall (); } ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); @@ -1424,14 +1534,14 @@ namespace Mono.CSharp { ca, CallingConventions, parameters.GetMetaInfo ()); - spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, TypeManager.void_type, ConstructorBuilder, parameters, ModFlags); + spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, ConstructorBuilder, parameters, ModFlags); Parent.MemberCache.AddMember (spec); // It's here only to report an error if (block != null && block.IsIterator) { - member_type = TypeManager.void_type; - Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler); + member_type = Compiler.BuiltinTypes.Void; + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); } return true; @@ -1447,16 +1557,21 @@ namespace Mono.CSharp { Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor", Parent.GetSignatureForError ()); } + + // Set as internal implementation and reset block data + // to ensure no IL is generated ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall); + block = null; } if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) - PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder); + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder); if (OptAttributes != null) OptAttributes.Emit (); base.Emit (); + parameters.ApplyAttributes (this, ConstructorBuilder); // // If we use a "this (...)" constructor initializer, then @@ -1465,7 +1580,7 @@ namespace Mono.CSharp { bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) || !(Initializer is ConstructorThisInitializer); - BlockContext bc = new BlockContext (this, block, TypeManager.void_type); + BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void); bc.Set (ResolveContext.Options.ConstructorScope); if (emit_field_initializers) @@ -1476,7 +1591,7 @@ namespace Mono.CSharp { // initializer, it must initialize all of the struct's fields. if ((Parent.PartialContainer.Kind == MemberKind.Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null)) - block.AddThisVariable (Parent, Location); + block.AddThisVariable (bc, Parent, Location); if (block != null && (ModFlags & Modifiers.STATIC) == 0){ if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null) @@ -1488,12 +1603,10 @@ namespace Mono.CSharp { } } - parameters.ApplyAttributes (ConstructorBuilder); - SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block); if (block != null) { - if (block.Resolve (null, bc, parameters, this)) { + if (block.Resolve (null, bc, this)) { EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType); ec.With (EmitContext.Options.ConstructorScope, true); @@ -1511,20 +1624,29 @@ namespace Mono.CSharp { if (declarative_security != null) { foreach (var de in declarative_security) { +#if STATIC + ConstructorBuilder.__AddDeclarativeSecurity (de); +#else ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif } } block = null; } - protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate) + protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) { // Is never override bestCandidate = null; return null; } + public override string GetSignatureForDocumentation () + { + return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation (); + } + public override string GetSignatureForError() { return base.GetSignatureForError () + parameters.GetSignatureForError (); @@ -1593,7 +1715,7 @@ namespace Mono.CSharp { /// /// Interface for MethodData class. Holds links to parent members to avoid member duplication. /// - public interface IMethodData + public interface IMethodData : IMemberContext { CallingConventions CallingConventions { get; } Location Location { get; } @@ -1602,20 +1724,24 @@ namespace Mono.CSharp { GenericMethod GenericMethod { get; } ParametersCompiled ParameterInfo { get; } MethodSpec Spec { get; } + bool IsAccessor { get; } Attributes OptAttributes { get; } ToplevelBlock Block { get; set; } EmitContext CreateEmitContext (ILGenerator ig); - string GetSignatureForError (); void EmitExtraSymbolInfo (SourceMethod source); } // // Encapsulates most of the Method's state // - public class MethodData { + public class MethodData + { +#if !STATIC static FieldInfo methodbuilder_attrs_field; +#endif + public readonly IMethodData method; public readonly GenericMethod GenericMethod; @@ -1673,24 +1799,25 @@ namespace Mono.CSharp { TypeContainer container = parent.PartialContainer; PendingImplementation pending = container.PendingImplementations; - if (pending != null){ - implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this); + MethodSpec ambig_iface_method; + if (pending != null) { + implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method); - if (member.InterfaceType != null){ - if (implementing == null){ + if (member.InterfaceType != null) { + if (implementing == null) { if (member is PropertyBase) { Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'", - method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType), - member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); + method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType), + member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); } else { Report.Error (539, method.Location, - "`{0}.{1}' in explicit interface declaration is not a member of interface", - TypeManager.CSharpName (member.InterfaceType), member.ShortName); + "`{0}.{1}' in explicit interface declaration is not a member of interface", + TypeManager.CSharpName (member.InterfaceType), member.ShortName); } return false; } - if (implementing.IsAccessor && !(method is AbstractPropertyEventMethod)) { + if (implementing.IsAccessor && !method.IsAccessor) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", member.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); @@ -1698,8 +1825,7 @@ namespace Mono.CSharp { } } else { if (implementing != null) { - AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod; - if (prop_method == null) { + if (!method.IsAccessor) { if (implementing.IsAccessor) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'", @@ -1711,7 +1837,7 @@ namespace Mono.CSharp { Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ()); } else { - PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod; + PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod; if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) { Report.SymbolRelatedToPreviousError (implementing); Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'", @@ -1721,6 +1847,8 @@ namespace Mono.CSharp { } } } + } else { + ambig_iface_method = null; } // @@ -1741,6 +1869,15 @@ namespace Mono.CSharp { Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier", method.GetSignatureForError ()); } + + if (ambig_iface_method != null) { + Report.SymbolRelatedToPreviousError (ambig_iface_method); + Report.SymbolRelatedToPreviousError (implementing); + Report.Warning (473, 2, method.Location, + "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead", + method.GetSignatureForError ()); + } + } else { if (implementing.DeclaringType.IsInterface) { // @@ -1794,7 +1931,7 @@ namespace Mono.CSharp { // clear the pending implementation flag (requires explicit methods to be defined first) // parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName, - member.InterfaceType, this, member.IsExplicitImpl); + member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method); // // Update indexer accessor name to match implementing abstract accessor @@ -1843,6 +1980,9 @@ namespace Mono.CSharp { builder.SetParameters (p_types); builder.SetReturnType (return_type); if (builder.Attributes != flags) { +#if STATIC + builder.__SetAttributes (flags); +#else try { if (methodbuilder_attrs_field == null) methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance); @@ -1850,6 +1990,7 @@ namespace Mono.CSharp { } catch { container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes"); } +#endif } } @@ -1861,14 +2002,16 @@ namespace Mono.CSharp { if (GenericMethod != null) GenericMethod.EmitAttributes (); - method.ParameterInfo.ApplyAttributes (MethodBuilder); + var mc = (IMemberContext) method; + + method.ParameterInfo.ApplyAttributes (mc, MethodBuilder); SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block); ToplevelBlock block = method.Block; if (block != null) { - BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType); - if (block.Resolve (null, bc, method.ParameterInfo, method)) { + BlockContext bc = new BlockContext (mc, block, method.ReturnType); + if (block.Resolve (null, bc, method)) { EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ()); if (!ec.HasReturnLabel && bc.HasReturnLabel) { ec.ReturnLabel = bc.ReturnLabel; @@ -1933,11 +2076,8 @@ namespace Mono.CSharp { MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location); method_expr.InstanceExpression = new BaseThis (base_type, Location); - ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation); - new_block.EndLocation = Block.EndLocation; - - Block finaly_block = new ExplicitBlock (new_block, Location, Location); - Block try_block = new Block (new_block, block); + var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation); + var finaly_block = new ExplicitBlock (block, Location, Location); // // 0-size arguments to avoid CS0250 error @@ -1945,9 +2085,9 @@ namespace Mono.CSharp { // debugger scope // finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); - new_block.AddStatement (new TryFinally (try_block, finaly_block, Location)); - block = new_block; + var tf = new TryFinally (try_block, finaly_block, Location); + block.WrapIntoDestructor (tf, try_block); } base.Emit (); @@ -1960,7 +2100,7 @@ namespace Mono.CSharp { protected override bool ResolveMemberType () { - member_type = TypeManager.void_type; + member_type = Compiler.BuiltinTypes.Void; return true; } @@ -1976,7 +2116,7 @@ namespace Mono.CSharp { public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData { protected MethodData method_data; protected ToplevelBlock block; - protected Dictionary declarative_security; + protected SecurityType declarative_security; protected readonly string prefix; @@ -2021,6 +2161,12 @@ namespace Mono.CSharp { return new EmitContext (this, ig, ReturnType); } + public bool IsAccessor { + get { + return true; + } + } + public bool IsExcluded () { return false; @@ -2059,9 +2205,7 @@ namespace Mono.CSharp { } if (a.IsValidSecurityAttribute ()) { - if (declarative_security == null) - declarative_security = new Dictionary (); - a.ExtractSecurityPermissionSet (declarative_security); + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); return; } @@ -2097,23 +2241,16 @@ namespace Mono.CSharp { method_data.Emit (parent); if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) - PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder); + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder); if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)) - PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder); + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder); - if (ReturnType == InternalType.Dynamic) { + if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); - PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder); - } else { - var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType); - if (trans_flags != null) { - var pa = PredefinedAttributes.Get.DynamicTransform; - if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) { - return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); - return_attributes.Builder.SetCustomAttribute ( - new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags })); - } - } + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.HasDynamicElement) { + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location); } if (OptAttributes != null) @@ -2121,7 +2258,11 @@ namespace Mono.CSharp { if (declarative_security != null) { foreach (var de in declarative_security) { +#if STATIC + method_data.MethodBuilder.__AddDeclarativeSecurity (de); +#else method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif } } @@ -2143,6 +2284,12 @@ namespace Mono.CSharp { return false; } + public override string GetSignatureForDocumentation () + { + // should not be called + throw new NotSupportedException (); + } + public override bool IsClsComplianceRequired() { return false; @@ -2275,12 +2422,12 @@ namespace Mono.CSharp { if (!base.Define ()) return false; - if (block != null && block.IsIterator && !(Parent is IteratorStorey)) { + if (block != null && block.IsIterator) { // // Current method is turned into automatically generated // wrapper which creates an instance of iterator // - Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler); + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); ModFlags |= Modifiers.DEBUGGER_HIDDEN; } @@ -2295,12 +2442,12 @@ namespace Mono.CSharp { TypeSpec first_arg_type = ParameterTypes [0]; TypeSpec first_arg_type_unwrap = first_arg_type; - if (TypeManager.IsNullableType (first_arg_type)) - first_arg_type_unwrap = TypeManager.GetTypeArguments (first_arg_type) [0]; + if (first_arg_type.IsNullableType) + first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type); TypeSpec return_type_unwrap = return_type; - if (TypeManager.IsNullableType (return_type)) - return_type_unwrap = TypeManager.GetTypeArguments (return_type) [0]; + if (return_type.IsNullableType) + return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type); // // Rules for conversion operators @@ -2313,9 +2460,9 @@ namespace Mono.CSharp { } TypeSpec conv_type; - if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) { + if (declaring_type == return_type || declaring_type == return_type_unwrap) { conv_type = first_arg_type; - } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) { + } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) { conv_type = return_type; } else { Report.Error (556, Location, @@ -2323,7 +2470,7 @@ namespace Mono.CSharp { return false; } - if (conv_type == InternalType.Dynamic) { + if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { Report.Error (1964, Location, "User-defined conversion `{0}' cannot convert to or from the dynamic type", GetSignatureForError ()); @@ -2338,20 +2485,20 @@ namespace Mono.CSharp { } if (conv_type.IsClass) { - if (TypeManager.IsSubclassOf (declaring_type, conv_type)) { + if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) { Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class", GetSignatureForError ()); return false; } - if (TypeManager.IsSubclassOf (conv_type, declaring_type)) { + if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) { Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class", GetSignatureForError ()); return false; } } } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) { - if (first_arg_type != declaring_type || parameters.Types[1] != TypeManager.int32_type) { + if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) { Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int"); return false; } @@ -2359,7 +2506,7 @@ namespace Mono.CSharp { // Checks for Unary operators if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) { - if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) { + if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) { Report.Error (448, Location, "The return type for ++ or -- operator must be the containing type or derived from the containing type"); return false; @@ -2371,14 +2518,14 @@ namespace Mono.CSharp { } } - if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) { + if (first_arg_type_unwrap != declaring_type) { Report.Error (562, Location, "The parameter type of a unary operator must be the containing type"); return false; } if (OperatorType == OpType.True || OperatorType == OpType.False) { - if (return_type != TypeManager.bool_type) { + if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) { Report.Error ( 215, Location, "The return type of operator True or False " + @@ -2387,14 +2534,14 @@ namespace Mono.CSharp { } } - } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) { + } else if (first_arg_type_unwrap != declaring_type) { // Checks for Binary operators var second_arg_type = ParameterTypes[1]; - if (TypeManager.IsNullableType (second_arg_type)) - second_arg_type = TypeManager.GetTypeArguments (second_arg_type)[0]; + if (second_arg_type.IsNullableType) + second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type); - if (!TypeManager.IsEqual (second_arg_type, declaring_type)) { + if (second_arg_type != declaring_type) { Report.Error (563, Location, "One of the parameters of a binary operator must be the containing type"); return false; @@ -2413,7 +2560,7 @@ namespace Mono.CSharp { return true; } - protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate) + protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) { // Operator cannot be override bestCandidate = null; @@ -2482,12 +2629,23 @@ namespace Mono.CSharp { } } + public override string GetSignatureForDocumentation () + { + string s = base.GetSignatureForDocumentation (); + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + s = s + "~" + ReturnType.GetSignatureForDocumentation (); + } + + return s; + } + public override string GetSignatureForError () { StringBuilder sb = new StringBuilder (); if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { sb.AppendFormat ("{0}.{1} operator {2}", - Parent.GetSignatureForError (), GetName (OperatorType), type_expr.GetSignatureForError ()); + Parent.GetSignatureForError (), GetName (OperatorType), + member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ()); } else { sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));