return null;
}
+ if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
+ Error (213, "You can not fix an already fixed expression");
+ return null;
+ }
+
// According to the specs, a variable is considered definitely assigned if you take
// its address.
if ((variable != null) && (variable.VariableInfo != null))
return ResolveOperator (ec);
}
+ public override Expression DoResolveLValue (EmitContext ec, Expression right)
+ {
+ if (Oper == Operator.Indirection)
+ return base.DoResolveLValue (ec, right);
+
+ Error (131, "The left-hand side of an assignment must be a " +
+ "variable, property or indexer");
+ return null;
+ }
+
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
ia.CacheTemporaries (ec);
+ //
+ // NOTE: We should probably handle three cases:
+ //
+ // * method invocation required.
+ // * direct stack manipulation possible
+ // * the object requires an "instance" field
+ //
if (temp_storage == null){
//
// Temporary improvement: if we are dealing with something that does
if (probe_type == null)
return null;
+ CheckObsoleteAttribute (probe_type);
+
expr = expr.Resolve (ec);
if (expr == null)
return null;
if (type == null)
return null;
+ CheckObsoleteAttribute (type);
+
eclass = ExprClass.Value;
if (expr is Constant){
return e;
}
+ if (type.IsPointer && !ec.InUnsafe) {
+ UnsafeError (loc);
+ return null;
+ }
expr = Convert.ExplicitConversion (ec, expr, type, loc);
return expr;
}
} else if (right is LongConstant){
long ll = ((LongConstant) right).Value;
- if (ll > 0)
+ if (ll >= 0)
right = new ULongConstant ((ulong) ll);
} else {
e = Convert.ImplicitNumericConversion (ec, right, l, loc);
bool overload_failed = false;
//
- // Special cases: string comapred to null
+ // Special cases: string or type parameter comapred to null
//
if (oper == Operator.Equality || oper == Operator.Inequality){
if ((l == TypeManager.string_type && (right is NullLiteral)) ||
return this;
}
+
+ if (l.IsGenericParameter && (right is NullLiteral)) {
+ if (l.BaseType == TypeManager.value_type) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ left = new BoxedCast (left);
+ Type = TypeManager.bool_type;
+ return this;
+ }
+
+ if (r.IsGenericParameter && (left is NullLiteral)) {
+ if (r.BaseType == TypeManager.value_type) {
+ Error_OperatorCannotBeApplied ();
+ return null;
+ }
+
+ right = new BoxedCast (right);
+ Type = TypeManager.bool_type;
+ return this;
+ }
+
+ // IntPtr equality
+ if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) {
+ Type = TypeManager.bool_type;
+
+ return this;
+ }
}
//
// If any of the arguments is a string, cast to string
//
- if (l == TypeManager.string_type){
- MethodBase method;
-
- if (r == TypeManager.void_type) {
- Error_OperatorCannotBeApplied ();
- return null;
- }
-
- if (r == TypeManager.string_type){
- if (left is Constant && right is Constant){
- StringConstant ls = (StringConstant) left;
- StringConstant rs = (StringConstant) right;
-
- return new StringConstant (
- ls.Value + rs.Value);
- }
-
- if (left is BinaryMethod){
- BinaryMethod b = (BinaryMethod) left;
-
- //
- // Call String.Concat (string, string, string) or
- // String.Concat (string, string, string, string)
- // if possible.
- //
- if (b.method == TypeManager.string_concat_string_string ||
- b.method == TypeManager.string_concat_string_string_string){
- int count = b.Arguments.Count;
-
- if (count == 2){
- ArrayList bargs = new ArrayList (3);
- bargs.AddRange (b.Arguments);
- bargs.Add (new Argument (right, Argument.AType.Expression));
- return new BinaryMethod (
- TypeManager.string_type,
- TypeManager.string_concat_string_string_string, bargs);
- } else if (count == 3){
- ArrayList bargs = new ArrayList (4);
- bargs.AddRange (b.Arguments);
- bargs.Add (new Argument (right, Argument.AType.Expression));
- return new BinaryMethod (
- TypeManager.string_type,
- TypeManager.string_concat_string_string_string_string, bargs);
- }
- }
- }
+ // Simple constant folding
+ if (left is StringConstant && right is StringConstant)
+ return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
- // string + string
- method = TypeManager.string_concat_string_string;
- } else {
- // string + object
- method = TypeManager.string_concat_object_object;
- right = Convert.ImplicitConversion (
- ec, right, TypeManager.object_type, loc);
- if (right == null){
- Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
- return null;
- }
- }
+ if (l == TypeManager.string_type || r == TypeManager.string_type) {
- //
- // Cascading concats will hold up to 2 arguments, any extras will be
- // reallocated above.
- //
- ArrayList args = new ArrayList (2);
- args.Add (new Argument (left, Argument.AType.Expression));
- args.Add (new Argument (right, Argument.AType.Expression));
-
- return new BinaryMethod (TypeManager.string_type, method, args);
- } else if (r == TypeManager.string_type){
- // object + string
-
- if (l == TypeManager.void_type) {
+ if (r == TypeManager.void_type || l == TypeManager.void_type) {
Error_OperatorCannotBeApplied ();
return null;
}
- left = Convert.ImplicitConversion (ec, left, TypeManager.object_type, loc);
- if (left == null){
- Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
- return null;
+ // try to fold it in on the left
+ if (left is StringConcat) {
+
+ //
+ // We have to test here for not-null, since we can be doubly-resolved
+ // take care of not appending twice
+ //
+ if (type == null){
+ type = TypeManager.string_type;
+ ((StringConcat) left).Append (ec, right);
+ return left.Resolve (ec);
+ } else {
+ return left;
+ }
}
- ArrayList args = new ArrayList (2);
- args.Add (new Argument (left, Argument.AType.Expression));
- args.Add (new Argument (right, Argument.AType.Expression));
- return new BinaryMethod (TypeManager.string_type, TypeManager.string_concat_object_object, args);
+ // Otherwise, start a new concat expression
+ return new StringConcat (ec, loc, left, right).Resolve (ec);
}
//
oper == Operator.BitwiseOr ||
oper == Operator.ExclusiveOr){
if (l == r){
- if (!((l == TypeManager.int32_type) ||
- (l == TypeManager.uint32_type) ||
- (l == TypeManager.short_type) ||
- (l == TypeManager.ushort_type) ||
- (l == TypeManager.int64_type) ||
- (l == TypeManager.uint64_type))){
+ if (((l == TypeManager.int32_type) ||
+ (l == TypeManager.uint32_type) ||
+ (l == TypeManager.short_type) ||
+ (l == TypeManager.ushort_type) ||
+ (l == TypeManager.int64_type) ||
+ (l == TypeManager.uint64_type))){
type = l;
+ } else {
+ Error_OperatorCannotBeApplied ();
+ return null;
}
} else {
Error_OperatorCannotBeApplied ();
// but on top of that we want for == and != to use a special path
// if we are comparing against null
//
- if (oper == Operator.Equality || oper == Operator.Inequality) {
+ if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
- if (left is NullLiteral || left is IntConstant && ((IntConstant) left).Value == 0) {
- right.Emit (ec);
- if (my_on_true)
- ig.Emit (OpCodes.Brtrue, target);
- else
- ig.Emit (OpCodes.Brfalse, target);
+ //
+ // put the constant on the rhs, for simplicity
+ //
+ if (left is Constant) {
+ Expression swap = right;
+ right = left;
+ left = swap;
+ }
- return;
- } else if (right is NullLiteral || right is IntConstant && ((IntConstant) right).Value == 0){
+ if (((Constant) right).IsZeroInteger) {
left.Emit (ec);
if (my_on_true)
ig.Emit (OpCodes.Brtrue, target);
else
ig.Emit (OpCodes.Brfalse, target);
- return;
- } else if (left is BoolConstant){
- right.Emit (ec);
- if (my_on_true != ((BoolConstant) left).Value)
- ig.Emit (OpCodes.Brtrue, target);
- else
- ig.Emit (OpCodes.Brfalse, target);
-
return;
} else if (right is BoolConstant){
left.Emit (ec);
right.Emit (ec);
Type t = left.Type;
- bool isUnsigned = is_unsigned (t);
+ bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
switch (oper){
case Operator.Equality:
break;
case Operator.LessThanOrEqual:
- if (t == TypeManager.double_type || t == TypeManager.float_type)
- isUnsigned = true;
-
if (onTrue)
if (isUnsigned)
ig.Emit (OpCodes.Ble_Un, target);
case Operator.GreaterThanOrEqual:
- if (t == TypeManager.double_type || t == TypeManager.float_type)
- isUnsigned = true;
if (onTrue)
if (isUnsigned)
ig.Emit (OpCodes.Bge_Un, target);
ig.MarkLabel (end);
return;
}
-
+
left.Emit (ec);
right.Emit (ec);
}
}
+ //
+ // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
+ // b, c, d... may be strings or objects.
+ //
+ public class StringConcat : Expression {
+ ArrayList operands;
+ bool invalid = false;
+
+
+ public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
+ {
+ this.loc = loc;
+ type = TypeManager.string_type;
+ eclass = ExprClass.Value;
+
+ operands = new ArrayList (2);
+ Append (ec, left);
+ Append (ec, right);
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (invalid)
+ return null;
+
+ return this;
+ }
+
+ public void Append (EmitContext ec, Expression operand)
+ {
+ //
+ // Constant folding
+ //
+ if (operand is StringConstant && operands.Count != 0) {
+ StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
+ if (last_operand != null) {
+ operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
+ return;
+ }
+ }
+
+ //
+ // Conversion to object
+ //
+ if (operand.Type != TypeManager.string_type) {
+ Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
+
+ if (no == null) {
+ Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
+ invalid = true;
+ }
+ operand = no;
+ }
+
+ operands.Add (operand);
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ MethodInfo concat_method = null;
+
+ //
+ // Are we also concating objects?
+ //
+ bool is_strings_only = true;
+
+ //
+ // Do conversion to arguments; check for strings only
+ //
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+ is_strings_only &= e.Type == TypeManager.string_type;
+ }
+
+ for (int i = 0; i < operands.Count; i ++) {
+ Expression e = (Expression) operands [i];
+
+ if (! is_strings_only && e.Type == TypeManager.string_type) {
+ // need to make sure this is an object, because the EmitParams
+ // method might look at the type of this expression, see it is a
+ // string and emit a string [] when we want an object [];
+
+ e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
+ }
+ operands [i] = new Argument (e, Argument.AType.Expression);
+ }
+
+ //
+ // Find the right method
+ //
+ switch (operands.Count) {
+ case 1:
+ //
+ // This should not be possible, because simple constant folding
+ // is taken care of in the Binary code.
+ //
+ throw new Exception ("how did you get here?");
+
+ case 2:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_string :
+ TypeManager.string_concat_object_object ;
+ break;
+ case 3:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_string_string :
+ TypeManager.string_concat_object_object_object ;
+ break;
+ case 4:
+ //
+ // There is not a 4 param overlaod for object (the one that there is
+ // is actually a varargs methods, and is only in corlib because it was
+ // introduced there before.).
+ //
+ if (!is_strings_only)
+ goto default;
+
+ concat_method = TypeManager.string_concat_string_string_string_string;
+ break;
+ default:
+ concat_method = is_strings_only ?
+ TypeManager.string_concat_string_dot_dot_dot :
+ TypeManager.string_concat_object_dot_dot_dot ;
+ break;
+ }
+
+ Invocation.EmitArguments (ec, concat_method, operands);
+ ec.ig.Emit (OpCodes.Call, concat_method);
+ }
+ }
+
//
// Object created with +/= on delegates
//
}
Expression op_true, op_false, op;
+ LocalTemporary left_temp;
public override Expression DoResolve (EmitContext ec)
{
return null;
}
+ left_temp = new LocalTemporary (ec, type);
+
ArrayList arguments = new ArrayList ();
- arguments.Add (new Argument (left, Argument.AType.Expression));
+ arguments.Add (new Argument (left_temp, Argument.AType.Expression));
arguments.Add (new Argument (right, Argument.AType.Expression));
method = Invocation.OverloadResolve (
ec, (MethodGroupExpr) operator_group, arguments, false, loc)
op = new StaticCallExpr (method, arguments, loc);
- op_true = GetOperatorTrue (ec, left, loc);
- op_false = GetOperatorFalse (ec, left, loc);
+ op_true = GetOperatorTrue (ec, left_temp, loc);
+ op_false = GetOperatorFalse (ec, left_temp, loc);
if ((op_true == null) || (op_false == null)) {
Error218 ();
return null;
ig.Emit (OpCodes.Nop);
- (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
left.Emit (ec);
+ left_temp.Store (ec);
+
+ (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
+ left_temp.Emit (ec);
ig.Emit (OpCodes.Br, end_target);
ig.MarkLabel (false_target);
op.Emit (ec);
return null;
}
+ CheckObsoleteAttribute (e.Type);
+
if (local_info.LocalBuilder == null)
return ec.RemapLocalLValue (local_info, right_side);
public enum AType : byte {
Expression,
Ref,
- Out
+ Out,
+ ArgList
};
public readonly AType ArgType;
public static string FullDesc (Argument a)
{
+ if (a.ArgType == AType.ArgList)
+ return "__arglist";
+
return (a.ArgType == AType.Ref ? "ref " :
(a.ArgType == AType.Out ? "out " : "")) +
TypeManager.CSharpName (a.Expr.Type);
{
ConstructedType ctype = Expr as ConstructedType;
if (ctype != null)
- Expr = ctype.GetMemberAccess (ec);
+ Expr = ctype.GetSimpleName (ec);
// FIXME: csc doesn't report any error if you try to use `ref' or
// `out' in a delegate creation expression.
if (ArgType == AType.Expression)
return true;
+ else {
+ //
+ // Catch errors where fields of a MarshalByRefObject are passed as ref or out
+ // This is only allowed for `this'
+ //
+ FieldExpr fe = Expr as FieldExpr;
+ if (fe != null && !fe.IsStatic){
+ Expression instance = fe.InstanceExpression;
+
+ 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");
+ return false;
+ }
+ }
+ }
+ }
if (Expr.eclass != ExprClass.Variable){
//
pr.AddressOf (ec, mode);
}
- } else
+ } else {
((IMemoryLocation)Expr).AddressOf (ec, mode);
+ }
} else
Expr.Emit (ec);
}
" does not resolve its type");
//
- // This is a special case since csc behaves this way. I can't find
- // it anywhere in the spec but oh well ...
+ // This is a special case since csc behaves this way.
//
if (argument_expr is NullLiteral &&
p == TypeManager.string_type &&
q == TypeManager.string_type)
return 0;
+ //
+ // csc behaves this way so we emulate it. Basically, if the argument
+ // is null and one of the types to compare is 'object' and the other
+ // is a reference type, we prefer the other.
+ //
+ // I can't find this anywhere in the spec but we can interpret this
+ // to mean that null can be of any type you wish in such a context
+ //
+ if (p != null && q != null) {
+ if (argument_expr is NullLiteral &&
+ !p.IsValueType &&
+ q == TypeManager.object_type)
+ return 1;
+ else if (argument_expr is NullLiteral &&
+ !q.IsValueType &&
+ p == TypeManager.object_type)
+ return 0;
+ }
+
if (p == q)
return 0;
// best method, we cant tell. This happens
// if we have:
//
- //
// interface IFoo {
// void DoIt ();
// }
//
// However, we have to consider that
// Trim (); is better than Trim (params char[] chars);
+ //
if (cand_count == 0 && argument_count == 0)
return best == null || best_params ? 1 : 0;
- if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
+ if ((candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS) &&
+ (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.ARGLIST))
if (cand_count != argument_count)
return 0;
{
string ret_type = "";
+ if (mb == null)
+ return "";
+
if (mb is MethodInfo)
ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
}
static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
- ArrayList arguments, ref MethodBase candidate)
+ ArrayList arguments, bool do_varargs,
+ ref MethodBase candidate)
{
if (!me.HasTypeArguments &&
!InferParamsTypeArguments (ec, arguments, ref candidate))
return false;
- return IsParamsMethodApplicable (ec, arguments, candidate);
+ return IsParamsMethodApplicable (ec, arguments, candidate, do_varargs);
}
/// <summary>
/// Determines if the candidate method, if a params method, is applicable
/// in its expanded form to the given set of arguments
/// </summary>
- static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
+ static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
+ MethodBase candidate, bool do_varargs)
{
int arg_count;
if (pd_count == 0)
return false;
- if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
+ int count = pd_count - 1;
+ if (do_varargs) {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
+ return false;
+ if (pd_count != arg_count)
+ return false;
+ } else {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.PARAMS)
return false;
+ }
- if (pd_count - 1 > arg_count)
+ if (count > arg_count)
return false;
if (pd_count == 1 && arg_count == 0)
// remains is when the number of parameters is
// less than or equal to the argument count.
//
- for (int i = 0; i < pd_count - 1; ++i) {
+ for (int i = 0; i < count; ++i) {
Argument a = (Argument) arguments [i];
}
+ if (do_varargs) {
+ Argument a = (Argument) arguments [count];
+ if (!(a.Expr is Arglist))
+ return false;
+
+ return true;
+ }
+
Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
for (int i = pd_count - 1; i < arg_count; i++) {
return true;
}
-
-
/// <summary>
/// Find the Applicable Function Members (7.4.2.1)
///
// and whether it is being considered in its
// normal or expanded form
//
+ // false is normal form, true is expanded form
+ //
Hashtable candidate_to_form = new PtrHashtable ();
applicable_type = candidate.DeclaringType;
found_applicable = true;
candidate_to_form [candidate] = false;
- } else if (IsParamsMethodApplicable (ec, me, Arguments, ref methods [i])) {
+ } else if (IsParamsMethodApplicable (
+ ec, me, Arguments,false, ref methods [i])) {
// Candidate is applicable in expanded form
- MethodBase candidate = methods [i];
+ MethodBase candidate = methods [i];
+ candidates.Add (candidate);
+ applicable_type = candidate.DeclaringType;
+ found_applicable = true;
+ candidate_to_form [candidate] = true;
+ } else if (IsParamsMethodApplicable (
+ ec, me, Arguments,true, ref methods [i])) {
+ // Candidate is applicable in expanded form
+ MethodBase candidate = methods [i];
candidates.Add (candidate);
applicable_type = candidate.DeclaringType;
found_applicable = true;
// applicable so we debar the params
// method.
//
- if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
- IsApplicable (ec, Arguments, method)))
- continue;
+ // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
+// IsApplicable (ec, Arguments, method)))
+// continue;
bool cand_params = (bool) candidate_to_form [candidate];
int x = BetterFunction (ec, Arguments,
if (chose_params_expanded)
parameter_type = TypeManager.GetElementType (parameter_type);
+ } else if (pm == Parameter.Modifier.ARGLIST){
+ continue;
} else {
//
// Check modifiers
is_base = true;
if (expr is ConstructedType)
- expr = ((ConstructedType) expr).GetMemberAccess (ec);
+ expr = ((ConstructedType) expr).GetSimpleName (ec);
expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
if (expr == null)
MethodInfo mi = method as MethodInfo;
if (mi != null) {
type = TypeManager.TypeToCoreType (mi.ReturnType);
- if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
+ if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null)) {
SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
+ return null;
+ }
+
+ Expression iexpr = mg.InstanceExpression;
+ if (mi.IsStatic && (iexpr != null) && !(iexpr is This)) {
+ if (mg.IdenticalTypeName)
+ mg.InstanceExpression = null;
+ else {
+ MemberAccess.error176 (loc, mi.Name);
+ return null;
+ }
+ }
}
if (type.IsPointer){
int count = arguments.Count - idx;
Argument a = (Argument) arguments [idx];
Type t = a.Expr.Type;
- string array_type;
- if (t.FullName != null)
- array_type = t.FullName + "[]";
- else
- array_type = t.Name + "[]";
- LocalBuilder array;
- array = ig.DeclareLocal (TypeManager.LookupType (array_type));
IntConstant.EmitInt (ig, count);
ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
- ig.Emit (OpCodes.Stloc, array);
int top = arguments.Count;
for (int j = idx; j < top; j++){
a = (Argument) arguments [j];
- ig.Emit (OpCodes.Ldloc, array);
+ ig.Emit (OpCodes.Dup);
IntConstant.EmitInt (ig, j - idx);
bool is_stobj, has_type_arg;
else
ig.Emit (op);
}
- ig.Emit (OpCodes.Ldloc, array);
}
/// <summary>
}
}
+ static Type[] GetVarargsTypes (EmitContext ec, MethodBase mb,
+ ArrayList arguments)
+ {
+ ParameterData pd = GetParameterData (mb);
+
+ if (arguments == null)
+ return new Type [0];
+
+ Argument a = (Argument) arguments [pd.Count - 1];
+ Arglist list = (Arglist) a.Expr;
+
+ return list.ArgumentTypes;
+ }
+
+ /// <summary>
+ /// This checks the ConditionalAttribute on the method
+ /// </summary>
+ static bool IsMethodExcluded (MethodBase method, EmitContext ec)
+ {
+ if (method.IsConstructor)
+ return false;
+
+ IMethodData md = TypeManager.GetMethod (method);
+ if (md != null)
+ return md.IsExcluded (ec);
+
+ // For some methods (generated by delegate class) GetMethod returns null
+ // because they are not included in builder_to_method table
+ if (method.DeclaringType is TypeBuilder)
+ return false;
+
+ return AttributeTester.IsConditionalMethodExcluded (method);
+ }
+
/// <remarks>
/// is_base tells whether we want to force the use of the `call'
/// opcode instead of using callvirt. Call is required to call
}
//
- // This checks the `ConditionalAttribute' on the method, and the
- // ObsoleteAttribute
+ // This checks ObsoleteAttribute on the method and on the declaring type
//
- TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
- if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
- return;
- if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+ ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (method);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (method), loc);
+
+ oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+ }
+
+
+ oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+ }
+
+ if (IsMethodExcluded (method, ec))
return;
if (!is_static){
}
EmitArguments (ec, method, Arguments);
+
+ OpCode call_op;
+ if (is_static || struct_call || is_base || (this_call && !method.IsVirtual))
+ call_op = OpCodes.Call;
+ else
+ call_op = OpCodes.Callvirt;
+
+ if ((method.CallingConvention & CallingConventions.VarArgs) != 0) {
+ Type[] varargs_types = GetVarargsTypes (ec, method, Arguments);
+ ig.EmitCall (call_op, (MethodInfo) method, varargs_types);
+ return;
+ }
+
//
// If you have:
// this.DoFoo ();
// and DoFoo is not virtual, you can omit the callvirt,
// because you don't need the null checking behavior.
//
- if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
- if (method is MethodInfo) {
- ig.Emit (OpCodes.Call, (MethodInfo) method);
- } else
- ig.Emit (OpCodes.Call, (ConstructorInfo) method);
- } else {
if (method is MethodInfo)
- ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
+ ig.Emit (call_op, (MethodInfo) method);
else
- ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
- }
+ ig.Emit (call_op, (ConstructorInfo) method);
}
public override void Emit (EmitContext ec)
if (type == null)
return null;
+ CheckObsoleteAttribute (type);
+
bool IsDelegate = TypeManager.IsDelegateType (type);
if (IsDelegate){
return this;
Expression ml;
- ml = MemberLookupFinal (ec, null, type, ".ctor",
+ ml = MemberLookupFinal (ec, type, type, ".ctor",
+ // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
MemberTypes.Constructor,
AllBindingFlags | BindingFlags.DeclaredOnly, loc);
/// initialization data and the other which does not need dimensions
/// specified but where initialization data is mandatory.
/// </remarks>
- public class ArrayCreation : ExpressionStatement {
+ public class ArrayCreation : Expression {
Expression requested_base_type;
ArrayList initializers;
//
// Emits the initializers for the array
//
- void EmitStaticInitializers (EmitContext ec, bool is_expression)
+ void EmitStaticInitializers (EmitContext ec)
{
//
// First, the static data
fb = RootContext.MakeStaticData (data);
- if (is_expression)
- ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Dup);
ig.Emit (OpCodes.Ldtoken, fb);
ig.Emit (OpCodes.Call,
TypeManager.void_initializearray_array_fieldhandle);
//
// This always expect the top value on the stack to be the array
//
- void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+ void EmitDynamicInitializers (EmitContext ec)
{
ILGenerator ig = ec.ig;
int dims = bounds.Count;
int [] current_pos = new int [dims];
int top = array_data.Count;
- LocalBuilder temp = ig.DeclareLocal (type);
-
- ig.Emit (OpCodes.Stloc, temp);
MethodInfo set = null;
num_automatic_initializers <= max_automatic_initializers) {
Type etype = e.Type;
- ig.Emit (OpCodes.Ldloc, temp);
+ ig.Emit (OpCodes.Dup);
for (int idx = 0; idx < dims; idx++)
IntConstant.EmitInt (ig, current_pos [idx]);
current_pos [j] = 0;
}
}
-
- if (is_expression)
- ig.Emit (OpCodes.Ldloc, temp);
}
void EmitArrayArguments (EmitContext ec)
}
}
- void DoEmit (EmitContext ec, bool is_statement)
+ public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
// initialized. num_automatic_initializers will always be zero. See
// CheckIndices.
if (num_automatic_initializers > max_automatic_initializers)
- EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+ EmitStaticInitializers (ec);
if (dynamic_initializers)
- EmitDynamicInitializers (ec, !is_statement);
+ EmitDynamicInitializers (ec);
}
}
- public override void Emit (EmitContext ec)
- {
- DoEmit (ec, false);
- }
-
- public override void EmitStatement (EmitContext ec)
- {
- DoEmit (ec, true);
- }
-
public object EncodeAsAttribute ()
{
if (!is_one_dimensional){
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
-
- ig.Emit (OpCodes.Ldarg_0);
+
+ ec.EmitThis ();
if (ec.TypeContainer is Struct)
ig.Emit (OpCodes.Ldobj, type);
}
ILGenerator ig = ec.ig;
if (ec.TypeContainer is Struct){
- ig.Emit (OpCodes.Ldarg_0);
+ ec.EmitThis ();
source.Emit (ec);
ig.Emit (OpCodes.Stobj, type);
} else {
public void AddressOf (EmitContext ec, AddressOp mode)
{
- ec.ig.Emit (OpCodes.Ldarg_0);
+ ec.EmitThis ();
// FIMXE
// FIGURE OUT WHY LDARG_S does not work
}
}
+ /// <summary>
+ /// Represents the `__arglist' construct
+ /// </summary>
+ public class ArglistAccess : Expression
+ {
+ public ArglistAccess (Location loc)
+ {
+ this.loc = loc;
+ }
+
+ public bool ResolveBase (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+ type = TypeManager.runtime_argument_handle_type;
+ return true;
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ if (!ResolveBase (ec))
+ return null;
+
+ if (ec.IsFieldInitializer || !ec.CurrentBlock.HasVarargs) {
+ Error (190, "The __arglist construct is valid only within " +
+ "a variable argument method.");
+ return null;
+ }
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.ig.Emit (OpCodes.Arglist);
+ }
+ }
+
+ /// <summary>
+ /// Represents the `__arglist (....)' construct
+ /// </summary>
+ public class Arglist : Expression
+ {
+ public readonly Argument[] Arguments;
+
+ public Arglist (Argument[] args, Location l)
+ {
+ Arguments = args;
+ loc = l;
+ }
+
+ public Type[] ArgumentTypes {
+ get {
+ Type[] retval = new Type [Arguments.Length];
+ for (int i = 0; i < Arguments.Length; i++)
+ retval [i] = Arguments [i].Type;
+ return retval;
+ }
+ }
+
+ public override Expression DoResolve (EmitContext ec)
+ {
+ eclass = ExprClass.Variable;
+ type = TypeManager.runtime_argument_handle_type;
+
+ foreach (Argument arg in Arguments) {
+ if (!arg.Resolve (ec, loc))
+ return null;
+ }
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ foreach (Argument arg in Arguments)
+ arg.Emit (ec);
+ }
+ }
+
//
// This produces the value that renders an instance, used by the iterators code
//
return null;
}
+ CheckObsoleteAttribute (typearg);
+
type = TypeManager.type_type;
eclass = ExprClass.Type;
return this;
}
type_queried = QueriedType.Type;
+ if (type_queried == null)
+ return null;
+
+ CheckObsoleteAttribute (type_queried);
+
if (!TypeManager.IsUnmanagedType (type_queried)){
Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
return null;
}
}
- static void error176 (Location loc, string name)
+ public static void error176 (Location loc, string name)
{
Report.Error (176, loc, "Static member `" +
name + "' cannot be accessed " +
"type name instead");
}
- static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
+ public static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Expression left, Location loc)
{
- if (left_original == null)
- return false;
-
- if (!(left_original is SimpleName))
+ SimpleName sn = left_original as SimpleName;
+ if (sn == null || left == null || left.Type.Name != sn.Name)
return false;
- SimpleName sn = (SimpleName) left_original;
-
- TypeExpr t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
- if (t != null)
- return true;
-
- return false;
+ return RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc) != null;
}
public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
if (member_lookup is FieldExpr){
FieldExpr fe = (FieldExpr) member_lookup;
- FieldInfo fi = fe.FieldInfo;
+ FieldInfo fi = fe.FieldInfo.Mono_GetGenericFieldDefinition ();
Type decl_type = fi.DeclaringType;
if (fi is FieldBuilder) {
Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
if (c != null) {
- object o = c.LookupConstantValue ();
- if (o == null)
+ object o;
+ if (!c.LookupConstantValue (out o))
return null;
-
+
object real_value = ((Constant) c.Expr).GetValue ();
return Constantify (real_value, fi.FieldType);
if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
if (left_is_explicit && !left_is_type &&
- !IdenticalNameAndTypeName (ec, left_original, loc)) {
+ !IdenticalNameAndTypeName (ec, left_original, member_lookup, loc)) {
error176 (loc, fe.FieldInfo.Name);
return null;
}
// accessors and private field etc so there's no need
// to transform ourselves.
//
+ ee.InstanceExpression = left;
return ee;
}
if (!left_is_explicit)
left = null;
+ ee.InstanceExpression = left;
+
return ResolveMemberAccess (ec, ml, left, loc, left_original);
}
}
if (member_lookup is IMemberExpr) {
IMemberExpr me = (IMemberExpr) member_lookup;
+ MethodGroupExpr mg = me as MethodGroupExpr;
if (left_is_type){
- MethodGroupExpr mg = me as MethodGroupExpr;
if ((mg != null) && left_is_explicit && left.Type.IsInterface)
mg.IsExplicitImpl = left_is_explicit;
if (!me.IsStatic){
if ((ec.IsFieldInitializer || ec.IsStatic) &&
- IdenticalNameAndTypeName (ec, left_original, loc))
+ IdenticalNameAndTypeName (ec, left_original, member_lookup, loc))
return member_lookup;
SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
} else {
if (!me.IsInstance){
- if (IdenticalNameAndTypeName (ec, left_original, loc))
+ if (IdenticalNameAndTypeName (ec, left_original, left, loc))
return member_lookup;
if (left_is_explicit) {
}
}
+ if ((mg != null) && IdenticalNameAndTypeName (ec, left_original, left, loc))
+ mg.IdenticalTypeName = true;
+
me.InstanceExpression = left;
}
Console.WriteLine ("Left is: " + left);
Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
- Environment.Exit (0);
+ Environment.Exit (1);
return null;
}
//
Expression original = expr;
- expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
+ expr = expr.Resolve (ec, flags | ResolveFlags.Intermediate | ResolveFlags.DisableFlowAnalysis);
if (expr == null)
return null;
expr_type = ((TypeExpr) expr).ResolveType (ec);
if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
- Error (122, "`" + expr_type + "' " +
- "is inaccessible because of its protection level");
+ Report.Error_T (122, loc, expr_type);
return null;
}
object value = en.LookupEnumValue (ec, Identifier, loc);
if (value != null){
+ ObsoleteAttribute oa = en.GetObsoleteAttribute (ec, Identifier);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, en.GetSignatureForError (), Location);
+ }
+
Constant c = Constantify (value, en.UnderlyingType);
return new EnumConstant (c, expr_type);
}
+ } else {
+ CheckObsoleteAttribute (expr_type);
+
+ FieldInfo fi = expr_type.GetField (Identifier);
+ if (fi != null) {
+ ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (fi);
+ if (oa != null)
+ AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (fi), Location);
+ }
}
}
} else
if (mg == null)
throw new InternalErrorException ();
- if (args.Resolve (ec) == false)
- return null;
-
- Type[] atypes = args.Arguments;
-
- int first_count = 0;
- MethodInfo first = null;
-
- ArrayList list = new ArrayList ();
- foreach (MethodBase mb in mg.Methods) {
- MethodInfo mi = mb as MethodInfo;
- if ((mi == null) || !mi.HasGenericParameters)
- continue;
-
- Type[] gen_params = mi.GetGenericArguments ();
-
- if (first == null) {
- first = mi;
- first_count = gen_params.Length;
- }
-
- if (gen_params.Length != atypes.Length)
- continue;
-
- list.Add (mi.BindGenericParameters (atypes));
- }
-
- if (list.Count > 0) {
- MethodGroupExpr new_mg = new MethodGroupExpr (
- list, mg.Location);
- new_mg.InstanceExpression = mg.InstanceExpression;
- new_mg.HasTypeArguments = true;
- return new_mg;
- }
-
- string name = expr_type + "." + Identifier;
-
- if (first != null)
- Report.Error (
- 305, loc, "Using the generic method `{0}' " +
- "requires {1} type arguments", name,
- first_count);
- else
- Report.Error (
- 308, loc, "The non-generic method `{0}' " +
- "cannot be used with type arguments", name);
-
- return null;
+ return mg.ResolveGeneric (ec, args);
}
// The following DoResolve/DoResolveLValue will do the definite assignment
ig.Emit (OpCodes.Ldelem_R8);
else if (type == TypeManager.intptr_type)
ig.Emit (OpCodes.Ldelem_I);
- else if (type.IsValueType){
+ else if (TypeManager.IsEnumType (type)){
+ EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
+ } else if (type.IsValueType){
ig.Emit (OpCodes.Ldelema, type);
ig.Emit (OpCodes.Ldobj, type);
} else if (type.IsGenericParameter)
MemberInfo [] mi = TypeManager.MemberLookup (
caller_type, caller_type, lookup_type, MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance |
- BindingFlags.DeclaredOnly, p_name);
+ BindingFlags.DeclaredOnly, p_name, null);
if (mi == null || mi.Length == 0)
return null;
Error (1511, "Keyword base is not allowed in static method");
return null;
}
+
+ if (ec.IsFieldInitializer){
+ Error (1512, "Keyword base is not available in the current context");
+ return null;
+ }
member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type,
member, AllMemberTypes, AllBindingFlags,
if (ltype == null)
return null;
+ if ((ltype == TypeManager.void_type) && (dim != "*")) {
+ Report.Error (1547, Location,
+ "Keyword 'void' cannot be used in this context");
+ return null;
+ }
+
int pos = 0;
while ((pos < dim.Length) && (dim [pos] == '[')) {
pos++;