[mcs] nonliteral constants pattern matching
[mono.git] / mcs / mcs / class.cs
index 0a46fd5b7ce8ae2ac0130b2a76e99c1ec00a5ccf..e84aef93322521f3d66993ef9fbfbc3f109b14a5 100644 (file)
@@ -13,6 +13,7 @@
 //
 
 using System;
+using System.Linq;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Security;
@@ -143,8 +144,8 @@ namespace Mono.CSharp
                        }
 
                        if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
-                               ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
-                                (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
+                               ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0 &&
+                                (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0)) {
                                         Report.SymbolRelatedToPreviousError (existing);
                                Report.Error (262, next_part.Location,
                                        "Partial declarations of `{0}' have conflicting accessibility modifiers",
@@ -171,10 +172,10 @@ namespace Mono.CSharp
                                }
                        }
 
-                       if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
-                               existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
-                       } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
-                               existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
+                       if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
+                               existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
+                       } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
+                               existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
                                existing.ModFlags |= next_part.ModFlags;
                        } else {
                                existing.ModFlags |= next_part.ModFlags;
@@ -423,7 +424,7 @@ namespace Mono.CSharp
                        }
 
                        public TypeSpec CurrentType {
-                               get { return tc.Parent.CurrentType; }
+                               get { return tc.PartialContainer.CurrentType; }
                        }
 
                        public TypeParameters CurrentTypeParameters {
@@ -552,7 +553,8 @@ namespace Mono.CSharp
                public int AnonymousMethodsCounter;
                public int MethodGroupsCounter;
 
-               static readonly string[] attribute_targets = new string[] { "type" };
+               static readonly string[] attribute_targets = new [] { "type" };
+               static readonly string[] attribute_targets_primary = new [] { "type", "method" };
 
                /// <remarks>
                ///  The pending methods that need to be implemented
@@ -729,6 +731,12 @@ namespace Mono.CSharp
                        }
                }
 
+               public ParametersCompiled PrimaryConstructorParameters { get; set; }
+
+               public Arguments PrimaryConstructorBaseArguments { get; set; }
+
+               public Location PrimaryConstructorBaseArgumentsStart { get; set; }
+
                public TypeParameters TypeParametersAll {
                        get {
                                return all_type_parameters;
@@ -737,7 +745,7 @@ namespace Mono.CSharp
 
                public override string[] ValidAttributeTargets {
                        get {
-                               return attribute_targets;
+                               return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
                        }
                }
 
@@ -887,6 +895,21 @@ namespace Mono.CSharp
 
                public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
                {
+                       if (a.Target == AttributeTargets.Method) {
+                               foreach (var m in members) {
+                                       var c = m as Constructor;
+                                       if (c == null)
+                                               continue;
+
+                                       if (c.IsPrimaryConstructor) {
+                                               c.ApplyAttributeBuilder (a, ctor, cdata, pa);
+                                               return;
+                                       }
+                               }
+
+                               throw new InternalErrorException ();
+                       }
+
                        if (has_normal_indexers && a.Type == pa.DefaultMember) {
                                Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
                                return;
@@ -1009,9 +1032,20 @@ namespace Mono.CSharp
 
                        for (int i = 0; i < initialized_fields.Count; ++i) {
                                FieldInitializer fi = initialized_fields [i];
+
+                               //
+                               // Clone before resolving otherwise when field initializer is needed
+                               // in more than 1 constructor any resolve after the initial one would
+                               // only took the resolved expression which is problem for expressions
+                               // that generate extra expressions or code during Resolve phase
+                               //
+                               var cloned = fi.Clone (new CloneContext ());
+
                                ExpressionStatement s = fi.ResolveStatement (ec);
-                               if (s == null)
+                               if (s == null) {
+                                       initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
                                        continue;
+                               }
 
                                //
                                // Field is re-initialized to its default value => removed
@@ -1021,6 +1055,7 @@ namespace Mono.CSharp
 
                                ec.AssignmentInfoOffset += fi.AssignmentOffset;
                                ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
+                               initialized_fields [i] = (FieldInitializer) cloned;
                        }
                }
 
@@ -1338,7 +1373,7 @@ namespace Mono.CSharp
 
                public SourceMethodBuilder CreateMethodSymbolEntry ()
                {
-                       if (Module.DeclaringAssembly.SymbolWriter == null)
+                       if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
                                return null;
 
                        var source_file = GetCompilationSourceFile ();
@@ -1506,6 +1541,14 @@ namespace Mono.CSharp
                                        PartialContainer.containers.AddRange (containers);
                                }
 
+                               if (PrimaryConstructorParameters != null) {
+                                       if (PartialContainer.PrimaryConstructorParameters != null) {
+                                               Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
+                                       } else {
+                                               PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
+                                       }
+                               }
+
                                members_defined = members_defined_ok = true;
                                caching_flags |= Flags.CloseTypeCreated;
                        } else {
@@ -1533,6 +1576,10 @@ namespace Mono.CSharp
                        }
 
                        if (iface_exprs != null) {
+                               if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
+                                       Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
+                               }
+
                                foreach (var iface_type in iface_exprs) {
                                        // Prevents a crash, the interface might not have been resolved: 442144
                                        if (iface_type == null)
@@ -1561,8 +1608,12 @@ namespace Mono.CSharp
                        // defined after current container
                        //
                        if (class_partial_parts != null) {
-                               foreach (var pp in class_partial_parts)
+                               foreach (var pp in class_partial_parts) {
+                                       if (pp.PrimaryConstructorBaseArguments != null)
+                                               PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
+
                                        pp.DoDefineBaseType ();
+                               }
 
                        }
 
@@ -1658,6 +1709,10 @@ namespace Mono.CSharp
                                return;
 
                        foreach (var member in members) {
+                               var pbm = member as PropertyBasedMember;
+                               if (pbm != null)
+                                       pbm.PrepareEmit ();
+
                                var pm = member as IParametersMember;
                                if (pm != null) {
                                        var mc = member as MethodOrOperator;
@@ -1670,6 +1725,7 @@ namespace Mono.CSharp
                                                continue;
 
                                        ((ParametersCompiled) p).ResolveDefaultValues (member);
+                                       continue;
                                }
 
                                var c = member as Const;
@@ -1744,7 +1800,7 @@ namespace Mono.CSharp
 
                protected virtual bool DoResolveTypeParameters ()
                {
-                       var tparams = CurrentTypeParameters;
+                       var tparams = MemberName.TypeParameters;
                        if (tparams == null)
                                return true;
 
@@ -1756,6 +1812,20 @@ namespace Mono.CSharp
                                        error = true;
                                        return false;
                                }
+
+                               if (IsPartialPart) {
+                                       var pc_tp = PartialContainer.CurrentTypeParameters [i];
+
+                                       tp.Create (spec, this);
+                                       tp.Define (pc_tp);
+
+                                       if (tp.OptAttributes != null) {
+                                               if (pc_tp.OptAttributes == null)
+                                                       pc_tp.OptAttributes = tp.OptAttributes;
+                                               else
+                                                       pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
+                                       }
+                               }
                        }
 
                        if (IsPartialPart) {
@@ -2009,10 +2079,10 @@ namespace Mono.CSharp
                                foreach (var member in members) {
                                        if (member is Event) {
                                                //
-                                               // An event can be assigned from same class only, so we can report
+                                               // An event can be assigned from same class only, report
                                                // this warning for all accessibility modes
                                                //
-                                               if (!member.IsUsed)
+                                               if (!member.IsUsed && !PartialContainer.HasStructLayout)
                                                        Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
 
                                                continue;
@@ -2030,12 +2100,15 @@ namespace Mono.CSharp
                                                continue;
 
                                        if (!member.IsUsed) {
-                                               if ((member.caching_flags & Flags.IsAssigned) == 0) {
-                                                       Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
-                                               } else {
-                                                       Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
-                                                               member.GetSignatureForError ());
+                                               if (!PartialContainer.HasStructLayout) {
+                                                       if ((member.caching_flags & Flags.IsAssigned) == 0) {
+                                                               Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
+                                                       } else {
+                                                               Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
+                                                                       member.GetSignatureForError ());
+                                                       }
                                                }
+
                                                continue;
                                        }
 
@@ -2498,12 +2571,15 @@ namespace Mono.CSharp
                public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
 
                SecurityType declarative_security;
+               protected Constructor generated_primary_constructor;
 
                protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
                        : base (parent, name, attrs, kind)
                {
                }
 
+               public ToplevelBlock PrimaryConstructorBlock { get; set; }
+
                protected override TypeAttributes TypeAttr {
                        get {
                                TypeAttributes ta = base.TypeAttr;
@@ -2531,7 +2607,7 @@ namespace Mono.CSharp
                                                symbol.GetSignatureForError ());
                                        return;
                                }
-                       
+
                                InterfaceMemberBase imb = symbol as InterfaceMemberBase;
                                if (imb == null || !imb.IsExplicitImpl) {
                                        Report.SymbolRelatedToPreviousError (this);
@@ -2575,19 +2651,30 @@ namespace Mono.CSharp
                        // The default static constructor is private
 
                        Modifiers mods;
+                       ParametersCompiled parameters = null;
                        if (is_static) {
                                mods = Modifiers.STATIC | Modifiers.PRIVATE;
+                               parameters = ParametersCompiled.EmptyReadOnlyParameters;
                        } else {
                                mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
+                               parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
                        }
 
-                       var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
-                       c.Initializer = new GeneratedBaseInitializer (Location);
+                       var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
+                       if (Kind == MemberKind.Class)
+                               c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
+
+                       if (PrimaryConstructorParameters != null && !is_static)
+                               c.IsPrimaryConstructor = true;
                        
                        AddConstructor (c, true);
-                       c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
-                               IsCompilerGenerated = true
-                       };
+                       if (PrimaryConstructorBlock == null) {
+                               c.Block = new ToplevelBlock (Compiler, parameters, Location) {
+                                       IsCompilerGenerated = true
+                               };
+                       } else {
+                               c.Block = PrimaryConstructorBlock;
+                       }
 
                        return c;
                }
@@ -2596,6 +2683,25 @@ namespace Mono.CSharp
                {
                        CheckProtectedModifier ();
 
+                       if (PrimaryConstructorParameters != null) {
+                               foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
+                                       if (p.Name == MemberName.Name) {
+                                               Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
+                                                       GetSignatureForError ());
+                                       }
+
+                                       if (CurrentTypeParameters != null) {
+                                               for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
+                                                       var tp = CurrentTypeParameters [i];
+                                                       if (p.Name == tp.Name) {
+                                                               Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
+                                                                       GetSignatureForError (), p.GetSignatureForError ());
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
                        base.DoDefineMembers ();
 
                        return true;
@@ -2635,7 +2741,7 @@ namespace Mono.CSharp
                        Modifiers.SEALED |
                        Modifiers.STATIC |
                        Modifiers.UNSAFE;
-
+                       
                public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
                        : base (parent, name, attrs, MemberKind.Class)
                {
@@ -2705,6 +2811,11 @@ namespace Mono.CSharp
                        }
 
                        if (IsStatic) {
+                               if (PrimaryConstructorParameters != null) {
+                                       Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
+                                       PrimaryConstructorParameters = null;
+                               }
+
                                foreach (var m in Members) {
                                        if (m is Operator) {
                                                Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
@@ -2732,8 +2843,8 @@ namespace Mono.CSharp
                                        Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
                                }
                        } else {
-                               if (!PartialContainer.HasInstanceConstructor)
-                                       DefineDefaultConstructor (false);
+                               if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
+                                       generated_primary_constructor = DefineDefaultConstructor (false);
                        }
 
                        return base.DoDefineMembers ();
@@ -2751,6 +2862,17 @@ namespace Mono.CSharp
                        }
                }
 
+               public override void GetCompletionStartingWith (string prefix, List<string> results)
+               {
+                       base.GetCompletionStartingWith (prefix, results);
+
+                       var bt = base_type;
+                       while (bt != null) {
+                               results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
+                               bt = bt.BaseType;
+                       }
+               }
+
                protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
                {
                        var ifaces = base.ResolveBaseTypes (out base_class);
@@ -2944,6 +3066,14 @@ namespace Mono.CSharp
                        return fts.CheckStructCycles ();
                }
 
+               protected override bool DoDefineMembers ()
+               {
+                       if (PrimaryConstructorParameters != null)
+                               generated_primary_constructor = DefineDefaultConstructor (false);
+
+                       return base.DoDefineMembers ();
+               }
+
                public override void Emit ()
                {
                        CheckStructCycles ();
@@ -2951,6 +3081,20 @@ namespace Mono.CSharp
                        base.Emit ();
                }
 
+               bool HasExplicitConstructor ()
+               {
+                       foreach (var m in Members) {
+                               var c = m as Constructor;
+                               if (c == null)
+                                       continue;
+
+                               if (!c.ParameterInfo.IsEmpty)
+                                       return true;
+                       }
+
+                       return false;
+               }
+
                public override bool IsUnmanagedType ()
                {
                        if (has_unmanaged_check_done)
@@ -3006,14 +3150,15 @@ namespace Mono.CSharp
 
                public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
                {
-                       if ((field.ModFlags & Modifiers.STATIC) == 0) {
-                               Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
+                       if ((field.ModFlags & Modifiers.STATIC) == 0 && !HasExplicitConstructor ()) {
+                               Report.Error (8054, field.Location, "`{0}': Structs without explicit constructors cannot contain members with initializers",
                                        field.GetSignatureForError ());
+
                                return;
                        }
+
                        base.RegisterFieldForInitialization (field, expression);
                }
-
        }
 
        /// <summary>
@@ -3652,25 +3797,29 @@ namespace Mono.CSharp
                                Report.SymbolRelatedToPreviousError (MemberType);
                                if (this is Property)
                                        Report.Error (53, Location,
-                                                     "Inconsistent accessibility: property type `" +
-                                                     MemberType.GetSignatureForError () + "' is less " +
-                                                     "accessible than property `" + GetSignatureForError () + "'");
+                                               "Inconsistent accessibility: property type `" +
+                                               MemberType.GetSignatureForError () + "' is less " +
+                                               "accessible than property `" + GetSignatureForError () + "'");
                                else if (this is Indexer)
                                        Report.Error (54, Location,
-                                                     "Inconsistent accessibility: indexer return type `" +
-                                                     MemberType.GetSignatureForError () + "' is less " +
-                                                     "accessible than indexer `" + GetSignatureForError () + "'");
+                                               "Inconsistent accessibility: indexer return type `" +
+                                               MemberType.GetSignatureForError () + "' is less " +
+                                               "accessible than indexer `" + GetSignatureForError () + "'");
                                else if (this is MethodCore) {
                                        if (this is Operator)
                                                Report.Error (56, Location,
-                                                             "Inconsistent accessibility: return type `" +
-                                                             MemberType.GetSignatureForError () + "' is less " +
-                                                             "accessible than operator `" + GetSignatureForError () + "'");
+                                                       "Inconsistent accessibility: return type `" +
+                                                       MemberType.GetSignatureForError () + "' is less " +
+                                                       "accessible than operator `" + GetSignatureForError () + "'");
                                        else
                                                Report.Error (50, Location,
-                                                             "Inconsistent accessibility: return type `" +
-                                                             MemberType.GetSignatureForError () + "' is less " +
-                                                             "accessible than method `" + GetSignatureForError () + "'");
+                                                       "Inconsistent accessibility: return type `" +
+                                                       MemberType.GetSignatureForError () + "' is less " +
+                                                       "accessible than method `" + GetSignatureForError () + "'");
+                               } else if (this is Event) {
+                                       Report.Error (7025, Location,
+                                               "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
+                                               MemberType.GetSignatureForError (), GetSignatureForError ());
                                } else {
                                        Report.Error (52, Location,
                                                      "Inconsistent accessibility: field type `" +