[mcs] More work on primary constructors
authorMarek Safar <marek.safar@gmail.com>
Tue, 15 Jul 2014 08:59:24 +0000 (10:59 +0200)
committerMarek Safar <marek.safar@gmail.com>
Tue, 15 Jul 2014 08:59:52 +0000 (10:59 +0200)
20 files changed:
mcs/errors/cs1644-37.cs [new file with mode: 0644]
mcs/errors/cs8036.cs [new file with mode: 0644]
mcs/errors/cs8037.cs [new file with mode: 0644]
mcs/errors/cs8038.cs [new file with mode: 0644]
mcs/errors/cs8039.cs [new file with mode: 0644]
mcs/errors/cs8043.cs [new file with mode: 0644]
mcs/errors/cs8049.cs [new file with mode: 0644]
mcs/errors/cs9001.cs [deleted file]
mcs/errors/cs9002.cs [deleted file]
mcs/errors/cs9003.cs [deleted file]
mcs/errors/cs9004.cs [deleted file]
mcs/mcs/assign.cs
mcs/mcs/class.cs
mcs/mcs/cs-parser.jay
mcs/mcs/expression.cs
mcs/mcs/method.cs
mcs/mcs/parameter.cs
mcs/tests/test-primary-ctor-06.cs [new file with mode: 0644]
mcs/tests/test-primary-ctor-07.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_5.xml

diff --git a/mcs/errors/cs1644-37.cs b/mcs/errors/cs1644-37.cs
new file mode 100644 (file)
index 0000000..37c997f
--- /dev/null
@@ -0,0 +1,7 @@
+// CS1644: Feature `primary constructor' cannot be used because it is not part of the C# 5.0 language specification
+// Line: 7
+// Compiler options: -langversion:5
+
+class C (int arg)
+{
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8036.cs b/mcs/errors/cs8036.cs
new file mode 100644 (file)
index 0000000..5969480
--- /dev/null
@@ -0,0 +1,10 @@
+// CS9001: Only one part of a partial type can declare primary constructor parameters
+// Line: 8
+
+partial class Part(int arg)
+{
+}
+
+partial class Part(int arg)
+{
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8037.cs b/mcs/errors/cs8037.cs
new file mode 100644 (file)
index 0000000..ea40954
--- /dev/null
@@ -0,0 +1,9 @@
+// CS9002: `S.S(long)': Instance constructor of type with primary constructor must specify `this' constructor initializer
+// Line: 6
+
+class S (int arg)
+{
+       public S (long l)
+       {
+       }
+}
diff --git a/mcs/errors/cs8038.cs b/mcs/errors/cs8038.cs
new file mode 100644 (file)
index 0000000..00780bc
--- /dev/null
@@ -0,0 +1,6 @@
+// CS9003: Primary constructor of type `Test<T>' has parameter of same name as type parameter `T'
+// Line: 4
+
+class Test<T>(T T) 
+{
+}
diff --git a/mcs/errors/cs8039.cs b/mcs/errors/cs8039.cs
new file mode 100644 (file)
index 0000000..d367928
--- /dev/null
@@ -0,0 +1,6 @@
+// CS9004: Primary constructor of type `Test' has parameter of same name as containing type
+// Line: 4
+
+class Test(object Test) 
+{
+}
\ No newline at end of file
diff --git a/mcs/errors/cs8043.cs b/mcs/errors/cs8043.cs
new file mode 100644 (file)
index 0000000..b7f9da8
--- /dev/null
@@ -0,0 +1,10 @@
+// CS8043: `S.S(long)': Structs with primary constructor cannot specify default constructor initializer
+// Line: 6
+
+struct S (int x)
+{
+       public S (long x)
+               : this ()
+       {
+       }
+}
diff --git a/mcs/errors/cs8049.cs b/mcs/errors/cs8049.cs
new file mode 100644 (file)
index 0000000..0689057
--- /dev/null
@@ -0,0 +1,11 @@
+// CS8049: Implemented interfaces cannot have arguments
+// Line: 6
+
+using System;
+
+class ID () : IDisposable ()
+{
+       public void Dispose ()
+       {
+       }
+}
diff --git a/mcs/errors/cs9001.cs b/mcs/errors/cs9001.cs
deleted file mode 100644 (file)
index 5969480..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// CS9001: Only one part of a partial type can declare primary constructor parameters
-// Line: 8
-
-partial class Part(int arg)
-{
-}
-
-partial class Part(int arg)
-{
-}
\ No newline at end of file
diff --git a/mcs/errors/cs9002.cs b/mcs/errors/cs9002.cs
deleted file mode 100644 (file)
index ea40954..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// CS9002: `S.S(long)': Instance constructor of type with primary constructor must specify `this' constructor initializer
-// Line: 6
-
-class S (int arg)
-{
-       public S (long l)
-       {
-       }
-}
diff --git a/mcs/errors/cs9003.cs b/mcs/errors/cs9003.cs
deleted file mode 100644 (file)
index 00780bc..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// CS9003: Primary constructor of type `Test<T>' has parameter of same name as type parameter `T'
-// Line: 4
-
-class Test<T>(T T) 
-{
-}
diff --git a/mcs/errors/cs9004.cs b/mcs/errors/cs9004.cs
deleted file mode 100644 (file)
index d367928..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// CS9004: Primary constructor of type `Test' has parameter of same name as containing type
-// Line: 4
-
-class Test(object Test) 
-{
-}
\ No newline at end of file
index 356768d8b74ed13484ade69a1340bdf5238bc9b6..472a393739f1a8cd0f5f68576f7bc57c1ddc2547 100644 (file)
@@ -645,6 +645,7 @@ namespace Mono.CSharp {
                public override void FlowAnalysis (FlowAnalysisContext fc)
                {
                        source.FlowAnalysis (fc);
+                       ((FieldExpr) target).SetFieldAssigned (fc);
                }
                
                public bool IsDefaultInitializer {
index 289dc5fe2cac434faf054d4b5f78573f0a4aee35..a19338958bd72afb5ab2d3b20b8ca5fda7e48665 100644 (file)
@@ -732,6 +732,10 @@ 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;
@@ -813,7 +817,7 @@ namespace Mono.CSharp
                                Report.Error (692, symbol.Location,
                                        "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
                        } else if (symbol is PrimaryConstructorField && mc is TypeParameter) {
-                               Report.Error (9003, symbol.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
+                               Report.Error (8038, symbol.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
                                        symbol.Parent.GetSignatureForError (), symbol.GetSignatureForError ());
                        } else {
                                Report.Error (102, symbol.Location,
@@ -1526,7 +1530,7 @@ namespace Mono.CSharp
 
                                if (PrimaryConstructorParameters != null) {
                                        if (PartialContainer.PrimaryConstructorParameters != null) {
-                                               Report.Error (9001, Location, "Only one part of a partial type can declare primary constructor parameters");
+                                               Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
                                        } else {
                                                PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
                                        }
@@ -1559,6 +1563,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)
@@ -2553,8 +2561,6 @@ namespace Mono.CSharp
                {
                }
 
-               public Arguments PrimaryConstructorBaseArguments { get; set; }
-
                protected override TypeAttributes TypeAttr {
                        get {
                                TypeAttributes ta = base.TypeAttr;
@@ -2584,7 +2590,7 @@ namespace Mono.CSharp
                                }
 
                                if (symbol is PrimaryConstructorField) {
-                                       Report.Error (9004, symbol.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
+                                       Report.Error (8039, symbol.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
                                                symbol.Parent.GetSignatureForError ());
                                        return;
                                }
@@ -2632,17 +2638,20 @@ 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, PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters, 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)
+                       if (PrimaryConstructorParameters != null && !is_static)
                                c.IsPrimaryConstructor = true;
                        
                        AddConstructor (c, true);
index 34d4cd33bec2d824ba51f9326f3cc2501e606d04..6becc05d0fe6ac64fcb4005dc69b6abdeb3c2920 100644 (file)
@@ -4698,6 +4698,9 @@ primary_parameters
 
                // Cannot use opt_formal_parameter_list because it can be shared instance for empty parameters
                lbag.AppendToMember (current_container, GetLocation ($1), GetLocation ($3));
+
+               if (lang_version < LanguageVersion.V_6)
+                       FeatureIsNotAvailable (GetLocation ($1), "primary constructor");
          }
        ;
 
@@ -4714,14 +4717,19 @@ opt_primary_parameters_with_class_base
          {
                $$ = $1;
          }
+       | primary_parameters class_base
+         {
+               $$ = $1;
+         }
        | primary_parameters class_base OPEN_PARENS
          {
                ++lexer.parsing_block;
+               current_type.PrimaryConstructorBaseArgumentsStart = GetLocation ($3);
          }
          opt_argument_list CLOSE_PARENS
          {
-               lbag.AppendToMember (current_container, GetLocation ($3), GetLocation ($6));
-               ((Class)current_type).PrimaryConstructorBaseArguments = (Arguments) $5;
+               lbag.AppendToMember (current_container, GetLocation ($6));
+               current_type.PrimaryConstructorBaseArguments = (Arguments) $5;
                --lexer.parsing_block;
 
                $$ = $1;
index 3c454aa1f14c2c5964aa3c66ceaa50081c75bb87..9b04d3a4a148c82d00378bbb24c2a740c738feb1 100644 (file)
@@ -7800,14 +7800,28 @@ namespace Mono.CSharp
                        : base (loc)
                {
                        this.type = type;
-                       eclass = ExprClass.Variable;
                }
 
-               protected override Expression DoResolve (ResolveContext ec)
+               protected override Expression DoResolve (ResolveContext rc)
                {
+                       eclass = ExprClass.Variable;
+
+                       var block = rc.CurrentBlock;
+                       if (block != null) {
+                               var top = block.ParametersBlock.TopBlock;
+                               if (top.ThisVariable != null)
+                                       variable_info = top.ThisVariable.VariableInfo;
+
+                       }
+
                        return this;
                }
 
+               public override Expression DoResolveLValue (ResolveContext rc, Expression right_side)
+               {
+                       return DoResolve (rc);
+               }
+
                public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
                {
                        return null;
@@ -7840,7 +7854,7 @@ namespace Mono.CSharp
                        }
                }
 
-               VariableInfo variable_info;
+               protected VariableInfo variable_info;
 
                public This (Location loc)
                {
index 2399133a9f1d372b1e89385ca994244660e62ca2..d368fe933b6eb4d04227bed03b9359fc92eeaa2f 100644 (file)
@@ -1620,7 +1620,6 @@ namespace Mono.CSharp {
                }
 
                public bool IsPrimaryConstructor { get; set; }
-
                
                MethodBase IMethodDefinition.Metadata {
                        get {
@@ -1709,12 +1708,12 @@ namespace Mono.CSharp {
                        if (!CheckBase ())
                                return false;
 
-                       if (Parent.PrimaryConstructorParameters != null && !IsPrimaryConstructor) {
-                               if (Parent.Kind == MemberKind.Struct) {
-                                       Report.Error (9009, Location, "`{0}': Structs with primary constructor cannot have explicit constructor",
+                       if (Parent.PrimaryConstructorParameters != null && !IsPrimaryConstructor && !IsStatic) {
+                               if (Parent.Kind == MemberKind.Struct && Initializer is ConstructorThisInitializer && Initializer.Arguments == null) {
+                                       Report.Error (8043, Location, "`{0}': Structs with primary constructor cannot specify default constructor initializer",
                                                GetSignatureForError ());
                                } else if (Initializer == null || Initializer is ConstructorBaseInitializer) {
-                                       Report.Error (9002, Location, "`{0}': Instance constructor of type with primary constructor must specify `this' constructor initializer",
+                                       Report.Error (8037, Location, "`{0}': Instance constructor of type with primary constructor must specify `this' constructor initializer",
                                                GetSignatureForError ());
                                }
                        }
@@ -1774,6 +1773,14 @@ namespace Mono.CSharp {
                        bc.Set (ResolveContext.Options.ConstructorScope);
 
                        if (block != null) {
+                               if (!IsStatic && Initializer == null && Parent.PartialContainer.Kind == MemberKind.Struct) {
+                                       //
+                                       // If this is a non-static `struct' constructor and doesn't have any
+                                       // initializer, it must initialize all of the struct's fields.
+                                       //
+                                       block.AddThisVariable (bc);
+                               }
+
                                //
                                // If we use a "this (...)" constructor initializer, then
                                // do not emit field initializers, they are initialized in the other constructor
@@ -1782,16 +1789,8 @@ namespace Mono.CSharp {
                                        Parent.PartialContainer.ResolveFieldInitializers (bc);
 
                                if (!IsStatic) {
-                                       if (Initializer == null) {
-                                               if (Parent.PartialContainer.Kind == MemberKind.Struct) {
-                                                       //
-                                                       // If this is a non-static `struct' constructor and doesn't have any
-                                                       // initializer, it must initialize all of the struct's fields.
-                                                       //
-                                                       block.AddThisVariable (bc);
-                                               } else if (Parent.PartialContainer.Kind == MemberKind.Class) {
-                                                       Initializer = new GeneratedBaseInitializer (Location, null);
-                                               }
+                                       if (Initializer == null && Parent.PartialContainer.Kind == MemberKind.Class) {
+                                               Initializer = new GeneratedBaseInitializer (Location, null);
                                        }
 
                                        if (Initializer != null) {
index a3f29def9bbe0c7d5b01f5003b803c9f0f617b71..2c6f1f44b9f99ba8eff9b4e30c9735a28476313d 100644 (file)
@@ -1431,9 +1431,11 @@ namespace Mono.CSharp {
                        expr = Child;
 
                        if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) {
-                               rc.Report.Error (1736, Location,
-                                       "The expression being assigned to optional parameter `{0}' must be a constant or default value",
-                                       p.Name);
+                               if (!(expr is ErrorExpression)) {
+                                       rc.Report.Error (1736, Location,
+                                               "The expression being assigned to optional parameter `{0}' must be a constant or default value",
+                                               p.Name);
+                               }
 
                                return;
                        }
diff --git a/mcs/tests/test-primary-ctor-06.cs b/mcs/tests/test-primary-ctor-06.cs
new file mode 100644 (file)
index 0000000..7d9ef1e
--- /dev/null
@@ -0,0 +1,15 @@
+using System;
+
+class ID () : IDisposable
+{
+       void IDisposable.Dispose ()
+       {
+       }
+}
+
+class X
+{
+       public static void Main ()
+       {
+       }
+}
\ No newline at end of file
diff --git a/mcs/tests/test-primary-ctor-07.cs b/mcs/tests/test-primary-ctor-07.cs
new file mode 100644 (file)
index 0000000..233cfd0
--- /dev/null
@@ -0,0 +1,29 @@
+using System;
+
+struct S (int x)
+{
+       public int y = x;
+
+       public S (char x)
+               : this (1)
+       {
+       }
+
+       static S ()
+       {
+       }
+}
+
+class X
+{
+       public static int Main ()
+       {
+               if (new S (-5).y != -5)
+                       return 1;
+
+               if (new S ('x').y != 1)
+                       return 2;
+
+               return 0;
+       }
+}
\ No newline at end of file
index 70fd4e54d6cc3d5e45e328c3873da9e80dda1647..78bee2958af487006ca0b14ee62f2c6d17e8484c 100644 (file)
       </method>\r
     </type>\r
   </test>\r
+  <test name="test-primary-ctor-06.cs">\r
+    <type name="ID">\r
+      <method name="Void System.IDisposable.Dispose()" attrs="481">\r
+        <size>2</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+    <type name="X">\r
+      <method name="Void Main()" attrs="150">\r
+        <size>2</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
+  <test name="test-primary-ctor-07.cs">\r
+    <type name="S">\r
+      <method name="Void .ctor(Char)" attrs="6278">\r
+        <size>9</size>\r
+      </method>\r
+      <method name="Void .cctor()" attrs="6289">\r
+        <size>2</size>\r
+      </method>\r
+      <method name="Void .ctor(Int32)" attrs="6278">\r
+        <size>15</size>\r
+      </method>\r
+    </type>\r
+    <type name="X">\r
+      <method name="Int32 Main()" attrs="150">\r
+        <size>69</size>\r
+      </method>\r
+      <method name="Void .ctor()" attrs="6278">\r
+        <size>7</size>\r
+      </method>\r
+    </type>\r
+  </test>\r
   <test name="test-static-using-01.cs">\r
     <type name="A.B.X">\r
       <method name="Int32 Test()" attrs="150">\r