+2005-02-18 Marek Safar <marek.safar@seznam.cz>
+
+ * class.cs (EmitFieldInitializers): Don't emit field initializer
+ for default values when optimilization is on.
+
+ * constant.cs (Constant.IsDefaultValue): New property.
+
+ * driver.cs: Add /optimize handling.
+
+ * constant.cs,
+ * ecore.cs,
+ * literal.cs: Implement new IsDefaultValue property.
+
+ * rootcontext.cs (Optimize): New field, holds /optimize option.
+
+2005-02-18 Raja R Harinath <rharinath@novell.com>
+
+ Fix crasher in re-opened #72347.
+ * namespace.cs (Namespace.Lookup): Return null if
+ DeclSpace.DefineType returns null.
+
+ Fix #72678.
+ * expression.cs (Argument.Resolve): Handle a case of CS0120 here.
+
+2005-02-18 Raja R Harinath <rharinath@novell.com>
+
+ Fix remainder of #63202. Change semantics of DoResolveLValue: it
+ now returns null if it cannot resolve to an lvalue.
+ * ecore.cs (Expression.DoResolveLValue): Return 'null' by default.
+ (Expression.ResolveLValue): Emit CS0131 error if DoResolveLValue
+ returned null. Remove check for SimpleName.
+ (EventExpr.DoResolveLValue): New.
+ * iterators.cs (Iterator.FieldExpression.DoResolveLValue): New.
+ * expression.cs (Argument.Error_LValueRequired): New. Move CS1510
+ error from ...
+ (Argument.Resolve): ... here. Use it. Use DoResolveLValue to
+ avoid CS0131 error.
+ (Unary.ResolveOperator): Move CS0211 check ...
+ (Unary.DoResolve): ... here. Use DoResolveLValue to avoid
+ CS0131 error.
+ (Unary.DoResolveLValue): Simplify.
+ (AddressOf.DoResolveLValue): New.
+ (ArrayAccess.DoResolveLValue): New.
+
+2005-02-16 Marek Safar <marek.safar@seznam.cz>
+
+ * attribute.cs (Attribute.Resolve): Add arguments casting for
+ when types doesn't match ctor arguments.
+
+2005-02-16 Raja R Harinath <rharinath@novell.com>
+
+ Fix parts of #63202.
+ * expression.cs (UnaryMutator.ResolveOperator): Remove redundant
+ lookup of operator in base type. Ensure that all checks happen
+ when the operator resolves to an "op_..." method.
+
2005-02-15 Raja R Harinath <rharinath@novell.com>
Fix #71992.
--- /dev/null
+This document describes all code optimalizations performed by Mono C# compiler
+when optimalizations are enabled via /optimize+ option.
+
+Optimalizations:
+
+* Instance field initializer to default value
+---------------------------------------------
+
+Code to optimize:
+
+class C
+{
+ enum E
+ {
+ Test
+ }
+
+ int i = 0; // Field will not be redundantly assigned
+ int i2 = new int (); // This will be also completely optimized out
+
+ E e = E.Test; // Even this will go out.
+
+}
+
+
+
return null;
}
+ object value = pos_values [j];
+ if (value != null && a.Type != value.GetType () && a.Type.IsPrimitive) {
+ bool fail;
+ pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail);
+ if (fail) {
+ // TODO: Can failed ?
+ throw new NotImplementedException ();
+ }
+ }
+
if (j < last_real_param)
continue;
if (a == null)
return false;
+ if (RootContext.Optimize) {
+ Constant c = e as Constant;
+ if (c != null) {
+ if (c.IsDefaultValue)
+ continue;
+ }
+ }
+
a.EmitStatement (ec);
}
return null;
}
+ public abstract bool IsDefaultValue {
+ get;
+ }
+
public abstract bool IsNegative {
get;
}
ec.ig.Emit (OpCodes.Ldc_I4_0);
}
+ public override bool IsDefaultValue {
+ get {
+ return !Value;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
return new IntConstant (Value);
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
return new IntConstant (Value);
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
return new IntConstant (Value);
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return Value < 0;
{
return new IntConstant (Value);
}
+
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
public override bool IsZeroInteger {
get { return Value == 0; }
return new IntConstant (Value);
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
{
return this;
}
+
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
public override bool IsNegative {
get {
return null;
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
return null;
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return Value < 0;
return null;
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
return null;
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return Value < 0;
return null;
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return Value < 0;
ig.Emit (OpCodes.Newobj, TypeManager.void_decimal_ctor_five_args);
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == 0;
+ }
+ }
+
public override bool IsNegative {
get {
return Value < 0;
ec.ig.Emit (OpCodes.Ldstr, Value);
}
+ public override bool IsDefaultValue {
+ get {
+ return Value == null;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
" -noconfig[+|-] Disables implicit references to assemblies\n" +
" -nostdlib[+|-] Does not load core libraries\n" +
" -nowarn:W1[,W2] Disables one or more warnings\n" +
+ " -optimize[+|-] Enables code optimalizations" + Environment.NewLine +
" -out:FNAME Specifies output file\n" +
" -pkg:P1[,Pn] References packages P1..Pn\n" +
" --expect-error X Expect that error X will be encountered\n" +
case "/optimize":
case "/optimize+":
+ RootContext.Optimize = true;
+ return true;
+
case "/optimize-":
+ RootContext.Optimize = false;
+ return true;
+
case "/incremental":
case "/incremental+":
case "/incremental-":
public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
- return DoResolve (ec);
+ return null;
}
//
/// </remarks>
public Expression ResolveLValue (EmitContext ec, Expression right_side)
{
+ int errors = Report.Errors;
Expression e = DoResolveLValue (ec, right_side);
- if (e != null){
- if (e is SimpleName){
- SimpleName s = (SimpleName) e;
- MemberLookupFailed (ec, null, ec.ContainerType, s.Name,
- ec.DeclSpace.Name, loc);
- return null;
- }
+ if (e == null) {
+ if (errors == Report.Errors)
+ Report.Error (131, Location, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");
+ return null;
+ }
+ if (e != null){
if (e.eclass == ExprClass.Invalid)
throw new Exception ("Expression " + e +
" ExprClass is Invalid after resolve");
public EmptyCast (Expression child, Type return_type)
{
eclass = child.eclass;
+ loc = child.Location;
type = return_type;
this.child = child;
}
child.Emit (ec);
}
+ public override bool IsDefaultValue {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
public override bool IsNegative {
get {
return false;
{
return Child.ConvertToInt ();
}
-
+
+ public override bool IsDefaultValue {
+ get {
+ return Child.IsDefaultValue;
+ }
+ }
+
public override bool IsZeroInteger {
get { return Child.IsZeroInteger; }
}
return true;
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return DoResolve (ec);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
if (instance_expr != null) {
return this;
case Operator.AddressOf:
- if (Expr.eclass != ExprClass.Variable){
- Error (211, "Cannot take the address of non-variables");
- return null;
- }
-
if (!ec.InUnsafe) {
UnsafeError (loc);
return null;
public override Expression DoResolve (EmitContext ec)
{
- if (Oper == Operator.AddressOf)
- Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
+ if (Oper == Operator.AddressOf) {
+ Expr = Expr.DoResolveLValue (ec, new EmptyExpression ());
+
+ if (Expr == null || Expr.eclass != ExprClass.Variable){
+ Error (211, "Cannot take the address of non-variables");
+ return null;
+ }
+ }
else
Expr = Expr.Resolve (ec);
public override Expression DoResolveLValue (EmitContext ec, Expression right)
{
if (Oper == Operator.Indirection)
- return base.DoResolveLValue (ec, right);
+ return DoResolve (ec);
- Error (131, "The left-hand side of an assignment must be a " +
- "variable, property or indexer");
return null;
}
expr.Emit (ec);
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return DoResolve (ec);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
//
mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
- if (mg == null && expr_type.BaseType != null)
- mg = MemberLookup (ec, expr_type.BaseType, op_name,
- MemberTypes.Method, AllBindingFlags, loc);
-
if (mg != null) {
method = StaticCallExpr.MakeSimpleCall (
ec, (MethodGroupExpr) mg, expr, loc);
type = method.Type;
- return this;
+ } else if (!IsIncrementableNumber (expr_type)) {
+ Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
+ TypeManager.CSharpName (expr_type) + "'");
+ return null;
}
//
type = expr_type;
if (expr.eclass == ExprClass.Variable){
LocalVariableReference var = expr as LocalVariableReference;
- if ((var != null) && var.IsReadOnly)
+ if ((var != null) && var.IsReadOnly) {
Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
- if (IsIncrementableNumber (expr_type) ||
- expr_type == TypeManager.decimal_type){
- return this;
+ return null;
}
- } else if (expr.eclass == ExprClass.IndexerAccess){
- IndexerAccess ia = (IndexerAccess) expr;
-
- expr = ia.ResolveLValue (ec, this);
+ } else if (expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess){
+ expr = expr.ResolveLValue (ec, this);
if (expr == null)
return null;
-
- return this;
- } else if (expr.eclass == ExprClass.PropertyAccess){
- PropertyExpr pe = (PropertyExpr) expr;
-
- if (pe.VerifyAssignable ())
- return this;
-
- return null;
} else {
expr.Error_UnexpectedKind ("variable, indexer or property access", loc);
return null;
}
- Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
- TypeManager.CSharpName (expr_type) + "'");
- return null;
+ return this;
}
public override Expression DoResolve (EmitContext ec)
return true;
}
+ void Error_LValueRequired (Location loc)
+ {
+ Report.Error (1510, loc, "An lvalue is required as an argument to out or ref");
+ }
+
public bool Resolve (EmitContext ec, Location loc)
{
if (ArgType == AType.Ref) {
return false;
}
}
- Expr = Expr.ResolveLValue (ec, Expr);
- } else if (ArgType == AType.Out)
- Expr = Expr.ResolveLValue (ec, EmptyExpression.Null);
+ Expr = Expr.DoResolveLValue (ec, Expr);
+ if (Expr == null)
+ Error_LValueRequired (loc);
+ } else if (ArgType == AType.Out) {
+ Expr = Expr.DoResolveLValue (ec, EmptyExpression.Null);
+ if (Expr == null)
+ Error_LValueRequired (loc);
+ }
else
Expr = Expr.Resolve (ec);
if (Expr == null)
return false;
+ if (Expr is IMemberExpr) {
+ IMemberExpr me = Expr as IMemberExpr;
+
+ //
+ // This can happen with the following code:
+ //
+ // class X {}
+ // class Y {
+ // public Y (X x) {}
+ // }
+ // class Z : Y {
+ // X X;
+ // public Z () : base (X) {}
+ // }
+ //
+ // SimpleNameResolve is conservative about flagging the X as
+ // an error since it has identical name and type. However,
+ // because there's no MemberAccess, that is not really justified.
+ // It is still simpler to fix it here, rather than in SimpleNameResolve.
+ //
+ if (me.IsInstance && me.InstanceExpression == null) {
+ SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
+ return false;
+ }
+ }
+
if (ArgType == AType.Expression)
return true;
else {
"A property or indexer can not be passed as an out or ref " +
"parameter");
} else {
- Report.Error (
- 1510, loc,
- "An lvalue is required as an argument to out or ref");
+ Error_LValueRequired (loc);
}
return false;
}
candidates [k++] = candidates [i];
-#if false
- //
- // Methods marked 'override' don't take part in 'applicable_type'
- // computation.
- //
- if (!me.IsBase &&
- candidate.IsVirtual &&
- (candidate.Attributes & MethodAttributes.NewSlot) == 0)
- continue;
-#endif
-
if (next_applicable_type == null ||
IsAncestralType (next_applicable_type, decl_type))
next_applicable_type = decl_type;
loc = l;
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return DoResolve (ec);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
#if false
this.field = field;
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ return DoResolve (ec);
+ }
+
public override Expression DoResolve (EmitContext ec)
{
FieldExpr fexpr = new FieldExpr (field.FieldBuilder, loc);
{
ec.ig.Emit (OpCodes.Ldnull);
}
-
+
+ public override bool IsDefaultValue {
+ get {
+ return true;
+ }
+ }
+
public override bool IsNegative {
get {
return false;
public static bool VerifyClsCompliance = true;
+ /// <summary>
+ /// Holds /optimize option
+ /// </summary>
+ public static bool Optimize = true;
+
public static LanguageVersion Version = LanguageVersion.Default;
//