2004-12-22 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / mcs / expression.cs
old mode 100755 (executable)
new mode 100644 (file)
index 494f2dd..e23aec2
@@ -217,6 +217,10 @@ namespace Mono.CSharp {
                                e = new IntConstant (-((ShortConstant) expr).Value);
                        else if (expr is UShortConstant)
                                e = new IntConstant (-((UShortConstant) expr).Value);
+                       else if (expr is SByteConstant)
+                               e = new IntConstant (-((SByteConstant) expr).Value);
+                       else if (expr is ByteConstant)
+                               e = new IntConstant (-((ByteConstant) expr).Value);
                        return e;
                }
 
@@ -237,7 +241,7 @@ namespace Mono.CSharp {
                                
                        case Operator.UnaryNegation:
                                result = TryReduceNegative (e);
-                               return true;
+                               return result != null;
                                
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
@@ -323,11 +327,22 @@ namespace Mono.CSharp {
 
                Expression ResolveOperator (EmitContext ec)
                {
-                       Type expr_type = Expr.Type;
+                       //
+                       // Step 1: Default operations on CLI native types.
+                       //
+
+                       // Attempt to use a constant folding operation.
+                       if (Expr is Constant){
+                               Expression result;
+                               
+                               if (Reduce (ec, (Constant) Expr, out result))
+                                       return result;
+                       }
 
                        //
-                       // Step 1: Perform Operator Overload location
+                       // Step 2: Perform Operator Overload location
                        //
+                       Type expr_type = Expr.Type;
                        Expression mg;
                        string op_name;
                        
@@ -353,18 +368,6 @@ namespace Mono.CSharp {
                        if (expr_type == null)
                                return null;
                        
-                       //
-                       // Step 2: Default operations on CLI native types.
-                       //
-
-                       // Attempt to use a constant folding operation.
-                       if (Expr is Constant){
-                               Expression result;
-                               
-                               if (Reduce (ec, (Constant) Expr, out result))
-                                       return result;
-                       }
-
                        switch (Oper){
                        case Operator.LogicalNot:
                                if (expr_type != TypeManager.bool_type) {
@@ -446,6 +449,7 @@ namespace Mono.CSharp {
                                                return null;
                                        }
                                        lr.local_info.AddressTaken = true;
+                                       lr.local_info.Used = true;
                                }
 
                                // According to the specs, a variable is considered definitely assigned if you take
@@ -2684,16 +2688,27 @@ namespace Mono.CSharp {
                                }
                        } else
                                left = left.Resolve (ec);
-                       right = right.Resolve (ec);
 
-                       if (left == null || right == null)
+                       if (left == null)
+                               return null;
+
+                       Constant lc = left as Constant;
+                       if (lc != null && lc.Type == TypeManager.bool_type && 
+                               ((oper == Operator.LogicalAnd && (bool)lc.GetValue () == false) ||
+                                (oper == Operator.LogicalOr && (bool)lc.GetValue () == true))) {
+
+                               // TODO: make a sense to resolve unreachable expression as we do for statement
+                               Report.Warning (429, 4, loc, "Unreachable expression code detected");
+                               return left;
+                       }
+
+                       right = right.Resolve (ec);
+                       if (right == null)
                                return null;
 
                        eclass = ExprClass.Value;
 
                        Constant rc = right as Constant;
-                       Constant lc = left as Constant;
-
                        if (rc != null & lc != null){
                                Expression e = ConstantFold.BinaryFold (
                                        ec, oper, lc, rc, loc);
@@ -3514,13 +3529,12 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       // Dead code optimalization
                        if (expr is BoolConstant){
                                BoolConstant bc = (BoolConstant) expr;
 
-                               if (bc.Value)
-                                       return trueExpr;
-                               else
-                                       return falseExpr;
+                               Report.Warning (429, 4, bc.Value ? falseExpr.Location : trueExpr.Location, "Unreachable expression code detected");
+                               return bc.Value ? trueExpr : falseExpr;
                        }
 
                        return this;
@@ -3589,6 +3603,11 @@ namespace Mono.CSharp {
                {
                        if (local_info == null) {
                                local_info = Block.GetLocalInfo (Name);
+
+                               // is out param
+                               if (lvalue_right_side == EmptyExpression.Null)
+                                       local_info.Used = true;
+
                                is_readonly = local_info.ReadOnly;
                        }
 
@@ -4142,8 +4161,9 @@ namespace Mono.CSharp {
 
                                        if (instance.GetType () != typeof (This)){
                                                if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
-                                                       Report.Error (197, loc,
-                                                                     "Can not pass a type that derives from MarshalByRefObject with out or ref");
+                                                       Report.SymbolRelatedToPreviousError (fe.InstanceExpression.Type);
+                                                       Report.Error (197, loc, "Cannot pass '{0}' as ref or out or take its address because it is a member of a marshal-by-reference class",
+                                                               fe.Name);
                                                        return false;
                                                }
                                        }
@@ -5147,6 +5167,9 @@ namespace Mono.CSharp {
                                }
                        }
 
+                       if (mg.InstanceExpression != null)
+                               mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
+
                        eclass = ExprClass.Value;
                        return this;
                }
@@ -5704,7 +5727,7 @@ namespace Mono.CSharp {
                        if (IsDelegate){
                                RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
                                if (RequestedType != null)
-                                       if (!(RequestedType is NewDelegate))
+                                       if (!(RequestedType is DelegateCreation))
                                                throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
                                return RequestedType;
                        }
@@ -7034,6 +7057,8 @@ namespace Mono.CSharp {
                        return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
                }
                
+               // TODO: possible optimalization
+               // Cache resolved constant result in FieldBuilder <-> expresion map
                public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
                                                              Expression left, Location loc,
                                                              Expression left_original)
@@ -7059,7 +7084,10 @@ namespace Mono.CSharp {
                                FieldInfo fi = fe.FieldInfo;
                                Type decl_type = fi.DeclaringType;
 
-                               if (fi is FieldBuilder) {
+                               bool is_emitted = fi is FieldBuilder;
+                               Type t = fi.FieldType;
+
+                               if (is_emitted) {
                                        Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
                                        
                                        if (c != null) {
@@ -7069,16 +7097,21 @@ namespace Mono.CSharp {
 
                                                object real_value = ((Constant) c.Expr).GetValue ();
 
-                                               return Constantify (real_value, fi.FieldType);
+                                               return Constantify (real_value, t);
                                        }
                                }
 
+                               // IsInitOnly is because of MS compatibility, I don't know why but they emit decimal constant as InitOnly
+                               if (fi.IsInitOnly && !is_emitted && t == TypeManager.decimal_type) {
+                                       object[] attrs = fi.GetCustomAttributes (TypeManager.decimal_constant_attribute_type, false);
+                                       if (attrs.Length == 1)
+                                               return new DecimalConstant (((System.Runtime.CompilerServices.DecimalConstantAttribute) attrs [0]).Value);
+                               }
+
                                if (fi.IsLiteral) {
-                                       Type t = fi.FieldType;
-                                       
                                        object o;
 
-                                       if (fi is FieldBuilder)
+                                       if (is_emitted)
                                                o = TypeManager.GetValue ((FieldBuilder) fi);
                                        else
                                                o = fi.GetValue (fi);
@@ -7115,7 +7148,7 @@ namespace Mono.CSharp {
                                        return exp;
                                }
 
-                               if (fi.FieldType.IsPointer && !ec.InUnsafe){
+                               if (t.IsPointer && !ec.InUnsafe){
                                        UnsafeError (loc);
                                        return null;
                                }
@@ -8162,6 +8195,8 @@ namespace Mono.CSharp {
                                UnsafeError (loc);
                                return null;
                        }
+
+                       instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
                        
                        eclass = ExprClass.IndexerAccess;
                        return this;
@@ -8232,6 +8267,8 @@ namespace Mono.CSharp {
                                }
                        }
                        
+                       instance_expr.CheckMarshallByRefAccess (ec.ContainerType);
+
                        eclass = ExprClass.IndexerAccess;
                        return this;
                }
@@ -8470,6 +8507,12 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public Expression Source {
+                       get {
+                               return source;
+                       }
+               }
+                       
                public override Expression DoResolve (EmitContext ec)
                {
                        //
@@ -8536,9 +8579,7 @@ namespace Mono.CSharp {
                                //
                                // For now, fall back to the full lookup in that case.
                                //
-                               type = RootContext.LookupType (
-                                       ec.DeclSpace, cname, false, loc);
-
+                               type = RootContext.LookupType (ec.DeclSpace, cname, false, loc);
                                if (type == null)
                                        return null;
                        }
@@ -8547,6 +8588,12 @@ namespace Mono.CSharp {
                                UnsafeError (loc);
                                return null;
                        }
+
+                       if (type.IsArray && (type.GetElementType () == TypeManager.arg_iterator_type ||
+                               type.GetElementType () == TypeManager.typed_reference_type)) {
+                               Report.Error (611, loc, "Array elements cannot be of type '{0}'", TypeManager.CSharpName (type.GetElementType ()));
+                               return null;
+                       }
                        
                        eclass = ExprClass.Type;
                        return this;