2001-12-29 Miguel de Icaza <miguel@ximian.com>
authorMiguel de Icaza <miguel@gnome.org>
Sat, 29 Dec 2001 20:25:56 +0000 (20:25 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Sat, 29 Dec 2001 20:25:56 +0000 (20:25 -0000)
* expression.cs (EmitCall): if a method is not virtual, then do
not use callvirt on it.

(ArrayAccess.EmitAssign): storing non-builtin value types (ie,
user defined stuff) requires the use of stobj, which takes an
address on the stack instead of an array and an index.  So emit
the Ldelema operation for it.

(EmitStoreOpcode): Use stobj for valuetypes.

(UnaryMutator.EmitCode): Use the right 1 value depending on
whether we are dealing with int64/uint64, float or doubles.

* class.cs (TypeContainer.AddConstructor): Fix the logic to define
constructors that I implemented last night.

(Constructor.IsDefault): Fix to work properly for static
constructors.

* cs-parser.jay (CheckDef): report method signature errors.
Update error number 103 to be 132.

* decl.cs: New AdditionResult enumeration value: MethodExists.
Although we do this check for methods later on in the semantic
analysis, catching repeated default constructors is so easy that
we catch these here.

svn path=/trunk/mcs/; revision=1751

mcs/mcs/ChangeLog
mcs/mcs/class.cs
mcs/mcs/cs-parser.jay
mcs/mcs/decl.cs
mcs/mcs/expression.cs
mcs/mcs/statement.cs

index 37236059cc296e93b840573b6e539cc30bec17d2..8821a4817655d4816f75b1a5c85defac3df5208f 100755 (executable)
@@ -1,5 +1,32 @@
 2001-12-29  Miguel de Icaza  <miguel@ximian.com>
 
+       * expression.cs (EmitCall): if a method is not virtual, then do
+       not use callvirt on it.
+
+       (ArrayAccess.EmitAssign): storing non-builtin value types (ie,
+       user defined stuff) requires the use of stobj, which takes an
+       address on the stack instead of an array and an index.  So emit
+       the Ldelema operation for it.
+
+       (EmitStoreOpcode): Use stobj for valuetypes.
+
+       (UnaryMutator.EmitCode): Use the right 1 value depending on
+       whether we are dealing with int64/uint64, float or doubles.
+
+       * class.cs (TypeContainer.AddConstructor): Fix the logic to define
+       constructors that I implemented last night.
+
+       (Constructor.IsDefault): Fix to work properly for static
+       constructors.
+
+       * cs-parser.jay (CheckDef): report method signature errors.
+       Update error number 103 to be 132.
+
+       * decl.cs: New AdditionResult enumeration value: MethodExists.
+       Although we do this check for methods later on in the semantic
+       analysis, catching repeated default constructors is so easy that
+       we catch these here. 
+       
        * expression.cs (Binary.DoNumericPromotions): Fix the uint64 type
        promotions code.
 
index f09c2cc15f1c8ca56d4bf89fe7564eadc5865345..5bc34fb6684698a40c78066aea6bc6a54e41f023 100755 (executable)
@@ -214,22 +214,28 @@ namespace Mono.CSharp {
 
                        bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
                        
-                       if (is_static)
+                       if (is_static){
                                have_static_constructor = true;
-                       else {
+                               if (default_static_constructor != null){
+                                       Console.WriteLine ("I have a static constructor already");
+                                       Console.WriteLine ("   " + default_static_constructor);
+                                       return AdditionResult.MethodExists;
+                               }
+
+                               default_static_constructor = c;
+                       } else {
+                               if (c.IsDefault ()){
+                                       if (default_constructor != null)
+                                               return AdditionResult.MethodExists;
+                                       default_constructor = c;
+                               }
+                               
                                if (instance_constructors == null)
                                        instance_constructors = new ArrayList ();
                                
                                instance_constructors.Add (c);
                        }
                        
-                       if (c.IsDefault ()) {
-                               if (is_static)
-                                       default_static_constructor = c;
-                               else
-                                       default_constructor = c;
-                       }
-                       
                        return AdditionResult.Success;
                }
                
@@ -525,15 +531,15 @@ namespace Mono.CSharp {
                                             new ConstructorBaseInitializer (null, new Location (-1)),
                                             new Location (-1));
                        
-                       AddConstructor (c);
-                       
-                       c.Block = new Block (null);
-                       
                        if (is_static)
                                mods = Modifiers.STATIC;
 
                        c.ModFlags = mods;
 
+                       AddConstructor (c);
+                       
+                       c.Block = new Block (null);
+                       
                }
 
                public void ReportStructInitializedInstanceError ()
@@ -2336,10 +2342,15 @@ namespace Mono.CSharp {
                //
                public bool IsDefault ()
                {
-                       return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
-                               (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
-                               (Initializer is ConstructorBaseInitializer) &&
-                               (Initializer.Arguments == null);
+                       if ((ModFlags & Modifiers.STATIC) != 0)
+                               return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
+                                       (Parameters.ArrayParameter == null ? true : Parameters.Empty);
+                       
+                       else
+                               return  (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
+                                       (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
+                                       (Initializer is ConstructorBaseInitializer) &&
+                                       (Initializer.Arguments == null);
                }
 
                //
index 68eca45b817c025a4976b753f20950b4ff577523..4b1da3117445d2f5ceec6faa1c9a60781eca7057 100755 (executable)
@@ -1327,7 +1327,7 @@ constructor_declaration
 
                        if (!c.Parameters.Empty){
                                Location l = lexer.Location;
-                               Report.Error (103, l, "Static constructors should not have parameters");
+                               Report.Error (132, l, "Static constructors should not have parameters");
                        }
                } 
                
@@ -3343,13 +3343,16 @@ CheckDef (AdditionResult result, string name)
                break;
 
 
-//     NEED TO HANDLE THIS IN SEMANTIC ANALYSIS:
-//
-//     case AdditionResult.MethodDuplicated:
-//             error (111, "Class `"+current_container.Name+
-//                         "' already defines a member called '" + 
-//                         name + "' with the same parameter types");
-//             break;
+               //
+               // This is handled only for static Constructors, because
+               // in reality we handle these by the semantic analysis later
+               //
+       case AdditionResult.MethodExists:
+               Report.Error (
+                       111, l, "Class `"+current_container.Name+
+                       "' already defines a member called '" + 
+                       name + "' with the same parameter types (more than one default constructor)");
+               break;
 
        case AdditionResult.EnclosingClash:
                Report.Error (542, l, "Member names cannot be the same as their enclosing type");
index b94bf5b936e293c6695c8c524a32b6385e932c2d..ebda903b5cf3484b6f12b65414caf569fed59d45 100755 (executable)
@@ -131,7 +131,14 @@ namespace Mono.CSharp {
                        ///   it looked like a constructor) but was not (because the name
                        ///   of the method is not the same as the container class
                        /// </summary>
-                       NotAConstructor
+                       NotAConstructor,
+
+                       /// <summary>
+                       ///   This is only used by static constructors to emit the
+                       ///   error 111, but this error for other things really
+                       ///   happens at another level for other functions.
+                       /// </summary>
+                       MethodExists
                }
 
        /// <summary>
index e6e90b13a43a0c07982e489364eff7ff2fc7a20a..1d66bda5c6a6a9cbae5417a4b62d505365d222af 100755 (executable)
@@ -634,17 +634,26 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
                        IAssignMethod ia = (IAssignMethod) expr;
-
-                       if (temp_storage == null)
-                               temp_storage = new LocalTemporary (ec, expr.Type);
+                       Type expr_type = expr.Type;
                        
+                       if (temp_storage == null)
+                               temp_storage = new LocalTemporary (ec, expr_type);
+
                        switch (mode){
                        case Mode.PreIncrement:
                        case Mode.PreDecrement:
                                if (method == null){
                                        expr.Emit (ec);
 
-                                       ig.Emit (OpCodes.Ldc_I4_1);
+                                       if (expr_type == TypeManager.uint64_type ||
+                                           expr_type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Ldc_I8, 1L);
+                                       else if (expr_type == TypeManager.double_type)
+                                               ig.Emit (OpCodes.Ldc_R8, 1.0);
+                                       else if (expr_type == TypeManager.float_type)
+                                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
+                                       else
+                                               ig.Emit (OpCodes.Ldc_I4_1);
                                
                                        if (mode == Mode.PreDecrement)
                                                ig.Emit (OpCodes.Sub);
@@ -670,7 +679,15 @@ namespace Mono.CSharp {
                                        else
                                                ig.Emit (OpCodes.Dup);
 
-                                       ig.Emit (OpCodes.Ldc_I4_1);
+                                       if (expr_type == TypeManager.uint64_type ||
+                                           expr_type == TypeManager.int64_type)
+                                               ig.Emit (OpCodes.Ldc_I8, 1L);
+                                       else if (expr_type == TypeManager.double_type)
+                                               ig.Emit (OpCodes.Ldc_R8, 1.0);
+                                       else if (expr_type == TypeManager.float_type)
+                                               ig.Emit (OpCodes.Ldc_R4, 1.0F);
+                                       else
+                                               ig.Emit (OpCodes.Ldc_I4_1);
                                
                                        if (mode == Mode.PostDecrement)
                                                ig.Emit (OpCodes.Sub);
@@ -3325,9 +3342,8 @@ namespace Mono.CSharp {
                                                // reference-type with a value-type argument need
                                                // to have their value boxed.  
 
+                                               struct_call = true;
                                                if (method.DeclaringType.IsValueType){
-                                                       struct_call = true;
-
                                                        //
                                                        // If the expression implements IMemoryLocation, then
                                                        // we can optimize and use AddressOf on the
@@ -3359,6 +3375,13 @@ namespace Mono.CSharp {
                        if (Arguments != null)
                                EmitArguments (ec, method, Arguments);
 
+                       if (method is MethodInfo){
+                               MethodInfo mi = (MethodInfo) method;
+
+                               if (!mi.IsVirtual)
+                                       is_static = true;
+                       }
+                       
                        if (is_static || struct_call){
                                if (method is MethodInfo)
                                        ig.Emit (OpCodes.Call, (MethodInfo) method);
@@ -3470,9 +3493,10 @@ namespace Mono.CSharp {
                                                        return null;
                                        }
                                }
-                               
+
                                method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
                                                                     Arguments, loc);
+                               
                        }
                        
                        if (method == null && !is_struct) {
@@ -5035,9 +5059,10 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Ldelem_R8);
                        else if (type == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Ldelem_I);
-                       else if (type.IsValueType)
+                       else if (type.IsValueType){
                                ig.Emit (OpCodes.Ldelema, type);
-                       else 
+                               ig.Emit (OpCodes.Ldobj, type);
+                       } else 
                                ig.Emit (OpCodes.Ldelem_Ref);
                }
 
@@ -5062,6 +5087,8 @@ namespace Mono.CSharp {
                                ig.Emit (OpCodes.Stelem_R8);
                        else if (t == TypeManager.intptr_type)
                                ig.Emit (OpCodes.Stelem_I);
+                       else if (t.IsValueType)
+                               ig.Emit (OpCodes.Stobj, t);
                        else
                                ig.Emit (OpCodes.Stelem_Ref);
                }
@@ -5147,10 +5174,20 @@ namespace Mono.CSharp {
                        foreach (Argument a in ea.Arguments)
                                a.Expr.Emit (ec);
 
-                       source.Emit (ec);
-
                        Type t = source.Type;
 
+                       //
+                       // The stobj opcode used by value types will need
+                       // an address on the stack, not really an array/array
+                       // pair
+                       //
+                       if (rank == 1){
+                               if (t.IsValueType && !TypeManager.IsBuiltinType (t))
+                                       ig.Emit (OpCodes.Ldelema, t);
+                       }
+                       
+                       source.Emit (ec);
+
                        if (rank == 1)
                                EmitStoreOpcode (ig, t);
                        else {
index e6ea61fd5165480e31f805f36e5e9fb4e42c7d57..f28260b006762a3770067388a3ba8a5da41a846f 100755 (executable)
@@ -524,6 +524,17 @@ namespace Mono.CSharp {
                                return false;
                        } 
 
+                       //
+                       // UGH: Non trivial.  This Br might cross a try/catch boundary
+                       // How can we tell?
+                       //
+                       // while () {
+                       //   try { ... } catch { continue; }
+                       // }
+                       //
+                       // From:
+                       // try {} catch { while () { continue; }}
+                       //
                        ec.ig.Emit (OpCodes.Br, begin);
                        return false;
                }