Move wapi shutdown to mono_cleanup () as TlsGetValue()/TlsSetValue() is used
[mono.git] / mcs / mcs / class.cs
index 9a7c9c4f1ed801b6cc4f664bd6d61c6cdf0bb65a..a662602161ed587469395ec001fb0d21d22a327e 100644 (file)
@@ -90,7 +90,7 @@ namespace Mono.CSharp {
                                return tc.GetSignatureForError ();
                        }
 
-                       public ExtensionMethodGroupExpr LookupExtensionMethod (TypeSpec extensionType, string name, int arity, Location loc)
+                       public IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
                        {
                                return null;
                        }
@@ -168,6 +168,8 @@ namespace Mono.CSharp {
                // Holds the compiler generated classes
                List<CompilerGeneratedClass> compiler_generated;
 
+               Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
+
                //
                // Pointers to the default constructor and the default static constructor
                //
@@ -286,6 +288,11 @@ namespace Mono.CSharp {
                        return AddToContainer (symbol, symbol.MemberName.Basename);
                }
 
+               public bool AddMember (MemberCore symbol, string name)
+               {
+                       return AddToContainer (symbol, name);
+               }
+
                protected virtual bool AddMemberType (TypeContainer ds)
                {
                        return AddToContainer (ds, ds.Basename);
@@ -843,7 +850,7 @@ namespace Mono.CSharp {
 
                                if (fne_resolved.Type.IsInterface) {
                                        for (int ii = 0; ii < j; ++ii) {
-                                               if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
+                                               if (fne_resolved.Type == ifaces [ii].Type) {
                                                        Report.Error (528, Location, "`{0}' is already listed in interface list",
                                                                fne_resolved.GetSignatureForError ());
                                                        break;
@@ -947,10 +954,10 @@ namespace Mono.CSharp {
                                        if (o_b == null || o_b.OperatorType != matching_type)
                                                continue;
 
-                                       if (!TypeManager.IsEqual (o_a.ReturnType, o_b.ReturnType))
+                                       if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
                                                continue;
 
-                                       if (!TypeSpecComparer.Default.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
+                                       if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
                                                continue;
 
                                        operators[i] = null;
@@ -1027,6 +1034,84 @@ namespace Mono.CSharp {
                        return true;
                }
 
+               //
+               // Creates a proxy base method call inside this container for hoisted base member calls
+               //
+               public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
+               {
+                       Method proxy_method;
+
+                       //
+                       // One proxy per base method is enough
+                       //
+                       if (hoisted_base_call_proxies == null) {
+                               hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
+                               proxy_method = null;
+                       } else {
+                               hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
+                       }
+
+                       if (proxy_method == null) {
+                               string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
+                               var cloned_params = ParametersCompiled.CreateFullyResolved (method.Parameters.FixedParameters, method.Parameters.Types);
+                               if (method.Parameters.HasArglist) {
+                                       cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
+                                       cloned_params.Types[0] = TypeManager.runtime_argument_handle_type;
+                               }
+
+                               GenericMethod generic_method;
+                               MemberName member_name;
+                               if (method.IsGeneric) {
+                                       //
+                                       // Copy all base generic method type parameters info
+                                       //
+                                       var hoisted_tparams = method.GenericDefinition.TypeParameters;
+                                       var targs = new TypeArguments ();
+                                       var type_params = new TypeParameter[hoisted_tparams.Length];
+                                       for (int i = 0; i < type_params.Length; ++i) {
+                                               var tp = hoisted_tparams[i];
+                                               targs.Add (new TypeParameterName (tp.Name, null, Location));
+                                               type_params[i] = new TypeParameter (tp, null, null, new MemberName (tp.Name), null);
+                                       }
+
+                                       member_name = new MemberName (name, targs, Location);
+                                       generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params,
+                                               new TypeExpression (method.ReturnType, Location), cloned_params);
+                               } else {
+                                       member_name = new MemberName (name);
+                                       generic_method = null;
+                               }
+
+                               // Compiler generated proxy
+                               proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location),
+                                       Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
+                                       member_name, cloned_params, null);
+
+                               var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location);
+
+                               var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
+                               mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
+
+                               // Get all the method parameters and pass them as arguments
+                               var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
+                               Statement statement;
+                               if (method.ReturnType == TypeManager.void_type)
+                                       statement = new StatementExpression (real_base_call);
+                               else
+                                       statement = new Return (real_base_call, Location);
+
+                               block.AddStatement (statement);
+                               proxy_method.Block = block;
+
+                               methods.Add (proxy_method);
+                               proxy_method.Define ();
+
+                               hoisted_base_call_proxies.Add (method, proxy_method);
+                       }
+
+                       return proxy_method.Spec;
+               }
+
                bool DefineBaseTypes ()
                {
                        iface_exprs = ResolveBaseTypes (out base_type_expr);
@@ -1490,7 +1575,8 @@ namespace Mono.CSharp {
                protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
                {
                        if (mcal != null) {
-                               foreach (MemberCore mc in mcal) {
+                               for (int i = 0; i < mcal.Count; ++i) {
+                                       MemberCore mc = (MemberCore) mcal[i];
                                        try {
                                                mc.Define ();
                                        } catch (Exception e) {
@@ -1823,10 +1909,11 @@ namespace Mono.CSharp {
                // Performs the validation on a Method's modifiers (properties have
                // the same properties).
                //
+               // TODO: Why is it not done at parse stage ?
+               //
                public bool MethodModifiersValid (MemberCore mc)
                {
                        const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
-                       const Modifiers va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
                        const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
                        bool ok = true;
                        var flags = mc.ModFlags;
@@ -1842,13 +1929,6 @@ namespace Mono.CSharp {
                                }
                        }
 
-                       if (Kind == MemberKind.Struct){
-                               if ((flags & va) != 0){
-                                       ModifiersExtensions.Error_InvalidModifier (mc.Location, "virtual or abstract", Report);
-                                       ok = false;
-                               }
-                       }
-
                        if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
                                Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
                                        mc.GetSignatureForError ());
@@ -1934,7 +2014,7 @@ namespace Mono.CSharp {
                        var ifaces = spec.Interfaces;
                        if (ifaces != null) {
                                foreach (TypeSpec t in ifaces){
-                                       if (TypeManager.IsEqual (t, mb.InterfaceType))
+                                       if (t == mb.InterfaceType)
                                                return true;
                                }
                        }
@@ -2037,14 +2117,14 @@ namespace Mono.CSharp {
 
                protected override bool AddToContainer (MemberCore symbol, string name)
                {
-                       if (name == MemberName.Name) {
+                       if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
                                if (symbol is TypeParameter) {
                                        Report.Error (694, symbol.Location,
                                                "Type parameter `{0}' has same name as containing type, or method",
                                                symbol.GetSignatureForError ());
                                        return false;
                                }
-
+                       
                                InterfaceMemberBase imb = symbol as InterfaceMemberBase;
                                if (imb == null || !imb.IsExplicitImpl) {
                                        Report.SymbolRelatedToPreviousError (this);
@@ -2149,7 +2229,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public override ExtensionMethodGroupExpr LookupExtensionMethod (TypeSpec extensionType, string name, int arity, Location loc)
+               public override IList<MethodSpec> LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceEntry scope)
                {
                        DeclSpace top_level = Parent;
                        if (top_level != null) {
@@ -2157,11 +2237,13 @@ namespace Mono.CSharp {
                                        top_level = top_level.Parent;
 
                                var candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name, arity);
-                               if (candidates != null)
-                                       return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
+                               if (candidates != null) {
+                                       scope = NamespaceEntry;
+                                       return candidates;
+                               }
                        }
 
-                       return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, loc);
+                       return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, ref scope);
                }
 
                protected override TypeAttributes TypeAttr {
@@ -2673,7 +2755,46 @@ namespace Mono.CSharp {
                }
        }
 
-       public abstract class InterfaceMemberBase : MemberBase {
+       public abstract class InterfaceMemberBase : MemberBase
+       {
+               //
+               // Common modifiers allowed in a class declaration
+               //
+               protected const Modifiers AllowedModifiersClass =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.VIRTUAL |
+                       Modifiers.SEALED |
+                       Modifiers.OVERRIDE |
+                       Modifiers.ABSTRACT |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN;
+
+               //
+               // Common modifiers allowed in a struct declaration
+               //
+               protected const Modifiers AllowedModifiersStruct =
+                       Modifiers.NEW |
+                       Modifiers.PUBLIC |
+                       Modifiers.PROTECTED |
+                       Modifiers.INTERNAL |
+                       Modifiers.PRIVATE |
+                       Modifiers.STATIC |
+                       Modifiers.OVERRIDE |
+                       Modifiers.UNSAFE |
+                       Modifiers.EXTERN;
+
+               //
+               // Common modifiers allowed in a interface declaration
+               //
+               protected const Modifiers AllowedModifiersInterface =
+                       Modifiers.NEW |
+                       Modifiers.UNSAFE;
+
                //
                // Whether this is an interface member.
                //
@@ -2799,7 +2920,7 @@ namespace Mono.CSharp {
                                        }
                                }
 
-                               if (!IsInterface && base_member.IsAbstract) {
+                               if (!IsInterface && base_member.IsAbstract && candidate == null) {
                                        Report.SymbolRelatedToPreviousError (base_member);
                                        Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
                                                GetSignatureForError (), base_member.GetSignatureForError ());
@@ -2822,7 +2943,7 @@ namespace Mono.CSharp {
                {
                        bool ok = true;
 
-                       if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE | Modifiers.OVERRIDE_UNCHECKED)) == 0) {
+                       if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
                                Report.SymbolRelatedToPreviousError (base_member);
                                Report.Error (506, Location,
                                        "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",