op_name = oper_names [(int) Oper];
- mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+ mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
Expression e = StaticCallExpr.MakeSimpleCall (
throw new Exception ("This should be caught by Resolve");
case Operator.UnaryNegation:
- if (ec.CheckState) {
+ if (ec.CheckState && type != TypeManager.float_type && type != TypeManager.double_type) {
ig.Emit (OpCodes.Ldc_I4_0);
if (type == TypeManager.int64_type)
ig.Emit (OpCodes.Conv_U8);
else
op_name = "op_Decrement";
- mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
+ mg = MemberLookup (ec.ContainerType, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
if (mg != null) {
method = StaticCallExpr.MakeSimpleCall (
if (expr == null)
return null;
} else {
- expr.Error_UnexpectedKind (ec, "variable, indexer or property access", loc);
+ expr.Error_UnexpectedKind (ec.DeclContainer, "variable, indexer or property access", loc);
return null;
}
Error_CannotConvertType (etype, probe_type, loc);
return null;
- }
+ }
+
+ public override bool GetAttributableValue (out object value)
+ {
+ return expr.GetAttributableValue (out value);
+ }
}
/// <summary>
Constant c = expr as Constant;
if (c != null) {
- c = c.TryReduce (ec, type, loc);
- if (c != null)
- return c;
+ try {
+ c = c.TryReduce (ec, type, loc);
+ if (c != null)
+ return c;
+ }
+ catch (OverflowException) {
+ return null;
+ }
}
if (type.IsPointer && !ec.InUnsafe) {
string op = oper_names [(int) oper];
MethodGroupExpr union;
- left_operators = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
+ left_operators = MemberLookup (ec.ContainerType, l, op, MemberTypes.Method, AllBindingFlags, loc);
if (r != l){
right_operators = MemberLookup (
- ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
+ ec.ContainerType, r, op, MemberTypes.Method, AllBindingFlags, loc);
union = Invocation.MakeUnionSet (left_operators, right_operators, loc);
} else
union = (MethodGroupExpr) left_operators;
local_info = Block.GetLocalInfo (Name);
// is out param
- if (lvalue_right_side == EmptyExpression.Null)
+ if (lvalue_right_side == EmptyExpression.OutAccess)
local_info.Used = true;
is_readonly = local_info.ReadOnly;
VariableInfo variable_info = local_info.VariableInfo;
if (lvalue_right_side != null){
if (is_readonly){
- if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.Null)
+ if (lvalue_right_side is LocalVariableReference || lvalue_right_side == EmptyExpression.OutAccess)
Report.Error (1657, loc, "Cannot pass `{0}' as a ref or out argument because it is a `{1}'",
Name, local_info.GetReadOnlyContext ());
+ else if (lvalue_right_side == EmptyExpression.LValueMemberAccess)
+ Report.Error (1654, loc, "Cannot assign to members of `{0}' because it is a `{1}'",
+ Name, local_info.GetReadOnlyContext ());
else
Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'",
Name, local_info.GetReadOnlyContext ());
vi = block.ParameterMap [idx];
if (ec.CurrentAnonymousMethod != null){
- if (is_ref){
+ if (is_ref && !block.Toplevel.IsLocalParameter (name)){
Report.Error (1628, Location, "Cannot use ref or out parameter `{0}' inside an anonymous method block",
par.Name);
return;
ILGenerator ig = ec.ig;
int arg_idx = idx;
- if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
- if (leave_copy)
- throw new InternalErrorException ();
-
- ec.EmitParameter (name);
+ if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
+ ec.EmitParameter (name, leave_copy, prepared, ref temp);
return;
}
public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
{
+ prepared = prepare_for_load;
if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
- ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load);
+ ec.EmitAssignParameter (name, source, leave_copy, prepare_for_load, ref temp);
return;
}
ILGenerator ig = ec.ig;
int arg_idx = idx;
- prepared = prepare_for_load;
+
if (!ec.MethodIsStatic)
arg_idx++;
return false;
}
+ int errors = Report.Errors;
Expr = Expr.DoResolveLValue (ec, Expr);
- if (Expr == null)
+ if (Expr == null && errors == Report.Errors)
Error_LValueRequired (loc);
} else if (ArgType == AType.Out) {
+ int errors = Report.Errors;
ec.InRefOutArgumentResolving = true;
- Expr = Expr.DoResolveLValue (ec, EmptyExpression.Null);
+ Expr = Expr.DoResolveLValue (ec, EmptyExpression.OutAccess);
ec.InRefOutArgumentResolving = false;
- if (Expr == null)
+ if (Expr == null && errors == Report.Errors)
Error_LValueRequired (loc);
}
else
}
}
}
-
- if (Expr.eclass != ExprClass.Variable){
- //
- // We just probe to match the CSC output
- //
- if (Expr.eclass == ExprClass.PropertyAccess ||
- Expr.eclass == ExprClass.IndexerAccess){
- Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
- Expr.GetSignatureForError ());
- } else {
- Error_LValueRequired (loc);
- }
- return false;
- }
return true;
}
MethodBase[] methods = me.Methods;
+ int nmethods = methods.Length;
+
+ if (!me.IsBase) {
+ //
+ // Methods marked 'override' don't take part in 'applicable_type'
+ // computation, nor in the actual overload resolution.
+ // However, they still need to be emitted instead of a base virtual method.
+ // So, we salt them away into the 'candidate_overrides' array.
+ //
+ // In case of reflected methods, we replace each overriding method with
+ // its corresponding base virtual method. This is to improve compatibility
+ // with non-C# libraries which change the visibility of overrides (#75636)
+ //
+ int j = 0;
+ for (int i = 0; i < methods.Length; ++i) {
+ MethodBase m = methods [i];
+ if (TypeManager.IsOverride (m)) {
+ if (candidate_overrides == null)
+ candidate_overrides = new ArrayList ();
+ candidate_overrides.Add (m);
+ m = TypeManager.TryGetBaseDefinition (m);
+ }
+ if (m != null)
+ methods [j++] = m;
+ }
+ nmethods = j;
+ }
+
+ int applicable_errors = Report.Errors;
+
//
// First we construct the set of applicable methods
//
bool is_sorted = true;
- for (int i = 0; i < methods.Length; i++){
+ for (int i = 0; i < nmethods; i++){
Type decl_type = methods [i].DeclaringType;
//
// If we have already found an applicable method
// we eliminate all base types (Section 14.5.5.1)
//
- if ((applicable_type != null) &&
- IsAncestralType (decl_type, applicable_type))
+ if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
continue;
- //
- // Methods marked 'override' don't take part in 'applicable_type'
- // computation, nor in the actual overload resolution.
- // However, they still need to be emitted instead of a base virtual method.
- // We avoid doing the 'applicable' test here, since it'll anyway be applied
- // to the base virtual function, and IsOverride is much faster than IsApplicable.
- //
- if (!me.IsBase && TypeManager.IsOverride (methods [i])) {
- if (candidate_overrides == null)
- candidate_overrides = new ArrayList ();
- candidate_overrides.Add (methods [i]);
- continue;
- }
-
//
// Check if candidate is applicable (section 14.4.2.1)
// Is candidate applicable in normal form?
//
- bool is_applicable = IsApplicable (
- ec, Arguments, arg_count, methods [i]);
+ bool is_applicable = IsApplicable (ec, Arguments, arg_count, methods [i]);
- if (!is_applicable &&
- (IsParamsMethodApplicable (
- ec, Arguments, arg_count, methods [i]))) {
+ if (!is_applicable && IsParamsMethodApplicable (ec, Arguments, arg_count, methods [i])) {
MethodBase candidate = methods [i];
if (candidate_to_form == null)
candidate_to_form = new PtrHashtable ();
}
}
+ if (applicable_errors != Report.Errors)
+ return null;
+
int candidate_top = candidates.Count;
if (applicable_type == null) {
// return by providing info about the closest match
//
int errors = Report.Errors;
- for (int i = 0; i < methods.Length; ++i) {
+ for (int i = 0; i < nmethods; ++i) {
MethodBase c = (MethodBase) methods [i];
ParameterData pd = TypeManager.GetParameterData (c);
return true;
}
+ private bool resolved = false;
public override Expression DoResolve (EmitContext ec)
{
+ if (resolved)
+ return this.method == null ? null : this;
+
+ resolved = true;
//
// First, resolve the expression that is used to
// trigger the invocation
}
MethodGroupExpr mg = (MethodGroupExpr) expr;
- method = OverloadResolve (ec, mg, Arguments, false, loc);
+ MethodBase method = OverloadResolve (ec, mg, Arguments, false, loc);
if (method == null)
return null;
mg.InstanceExpression.CheckMarshallByRefAccess (ec.ContainerType);
eclass = ExprClass.Value;
+ this.method = method;
return this;
}
/// <summary>
/// This checks the ConditionalAttribute on the method
/// </summary>
- static bool IsMethodExcluded (MethodBase method, EmitContext ec)
+ static bool IsMethodExcluded (MethodBase method)
{
if (method.IsConstructor)
return false;
IMethodData md = TypeManager.GetMethod (method);
if (md != null)
- return md.IsExcluded (ec);
+ return md.IsExcluded ();
// For some methods (generated by delegate class) GetMethod returns null
// because they are not included in builder_to_method table
method = TypeManager.void_array_copyto_array_int;
}
- if (ec.TestObsoleteMethodUsage) {
+ if (!ec.IsInObsoleteScope) {
//
// This checks ObsoleteAttribute on the method and on the declaring type
//
}
}
- if (IsMethodExcluded (method, ec))
+ if (IsMethodExcluded (method))
return;
if (!is_static){
MethodGroupExpr mg = ml as MethodGroupExpr;
if (mg == null) {
- ml.Error_UnexpectedKind (ec, "method group", loc);
+ ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
return null;
}
method = Invocation.OverloadResolve (ec, mg, Arguments, false, loc);
if (method == null) {
if (almostMatchedMembers.Count != 0)
- MemberLookupFailed (ec, type, type, ".ctor", null, true, loc);
+ MemberLookupFailed (ec.ContainerType, type, type, ".ctor", null, true, loc);
return null;
}
public bool ValidateInitializers (EmitContext ec, Type array_type)
{
if (initializers == null) {
- if (expect_initializers)
- return false;
- else
- return true;
+ return !expect_initializers;
}
if (underlying_type == null)
array_data = new ArrayList ();
bounds = new Hashtable ();
- bool ret;
-
if (arguments != null) {
- ret = CheckIndices (ec, initializers, 0, true);
- return ret;
+ return CheckIndices (ec, initializers, 0, true);
} else {
arguments = new ArrayList ();
- ret = CheckIndices (ec, initializers, 0, false);
-
- if (!ret)
+ if (!CheckIndices (ec, initializers, 0, false))
return false;
UpdateIndices (ec);
return false;
}
- return ret;
+ return true;
}
}
if (array_type_expr == null)
return false;
- type = array_type_expr.ResolveType (ec);
-
- if (!type.IsArray) {
- Error (622, "Can only use array initializer expressions to assign to array types. Try using a new expression instead.");
- return false;
- }
+ type = array_type_expr.ResolveType (ec);
underlying_type = TypeManager.GetElementType (type);
dimensions = type.GetArrayRank ();
if (is_builtin_type) {
Expression ml;
- ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
+ ml = MemberLookup (ec.ContainerType, type, ".ctor", MemberTypes.Constructor,
AllBindingFlags, loc);
if (!(ml is MethodGroupExpr)) {
- ml.Error_UnexpectedKind (ec, "method group", loc);
+ ml.Error_UnexpectedKind (ec.DeclContainer, "method group", loc);
return null;
}
}
}
- public object EncodeAsAttribute ()
+ public override bool GetAttributableValue (out object value)
{
if (!is_one_dimensional){
- Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
- return null;
+// Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
+ return base.GetAttributableValue (out value);
}
- if (array_data == null){
- Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
- return null;
+ if (array_data == null) {
+ Constant c = (Constant)((Argument)arguments [0]).Expr;
+ if (c.IsDefaultValue) {
+ value = new object [0];
+ return true;
+ }
+// Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
+ return base.GetAttributableValue (out value);
}
object [] ret = new object [array_data.Count];
- int i = 0;
- foreach (Expression e in array_data){
- object v;
-
- if (e is NullLiteral)
- v = null;
- else {
- if (!Attribute.GetAttributeArgumentExpression (e, Location, array_element_type, out v))
- return null;
+ for (int i = 0; i < ret.Length; ++i)
+ {
+ if (!((Expression)array_data [i]).GetAttributableValue (out ret [i])) {
+ value = null;
+ return false;
}
- ret [i++] = v;
}
- return ret;
+ value = ret;
+ return true;
}
}
ILGenerator ig = ec.ig;
if (ec.TypeContainer is Struct){
- ec.EmitThis ();
+ ec.EmitThis (false);
source.Emit (ec);
- if (leave_copy)
+
+ LocalTemporary t = null;
+ if (leave_copy) {
+ t = new LocalTemporary (ec, type);
ec.ig.Emit (OpCodes.Dup);
+ t.Store (ec);
+ }
+
ig.Emit (OpCodes.Stobj, type);
+
+ if (leave_copy)
+ t.Emit (ec);
} else {
throw new Exception ("how did you get here");
}
{
ILGenerator ig = ec.ig;
- ec.EmitThis ();
+ ec.EmitThis (false);
if (ec.TypeContainer is Struct)
ig.Emit (OpCodes.Ldobj, type);
}
public void AddressOf (EmitContext ec, AddressOp mode)
{
- ec.EmitThis ();
+ ec.EmitThis (true);
// FIMXE
// FIGURE OUT WHY LDARG_S does not work
/// Implements the typeof operator
/// </summary>
public class TypeOf : Expression {
- public Expression QueriedType;
+ readonly Expression QueriedType;
protected Type typearg;
public TypeOf (Expression queried_type, Location l)
ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
}
- public Type TypeArg {
- get { return typearg; }
+ public override bool GetAttributableValue (out object value)
+ {
+ value = typearg;
+ return true;
}
}
loc = l;
}
- public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
+ public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
if (alias == "global")
return new MemberAccess (RootNamespace.Global, identifier, loc).ResolveAsTypeStep (ec, silent);
int errors = Report.Errors;
- FullNamedExpression fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias);
+ FullNamedExpression fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
if (fne == null) {
if (errors == Report.Errors)
Report.Error (432, loc, "Alias `{0}' not found", alias);
fne = RootNamespace.Global;
} else {
int errors = Report.Errors;
- fne = ec.DeclSpace.NamespaceEntry.LookupAlias (alias);
+ fne = ec.DeclContainer.NamespaceEntry.LookupAlias (alias);
if (fne == null) {
if (errors == Report.Errors)
Report.Error (432, loc, "Alias `{0}' not found", alias);
if (new_expr is Namespace) {
Namespace ns = (Namespace) new_expr;
- FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc);
+ FullNamedExpression retval = ns.Lookup (ec.DeclContainer, Identifier, loc);
if (retval == null)
Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
Identifier, ns.FullName);
Error (23, "The `.' operator can not be applied to pointer operands (" +
TypeManager.CSharpName (expr_type) + ")");
return null;
+ } else if (expr_type == TypeManager.void_type) {
+ Error (23, "The `.' operator can not be applied to operands of type 'void'");
+ return null;
+ } else if (expr_type == TypeManager.anonymous_method_type){
+ Error (23, "The `.' operator can not be applied to anonymous methods");
}
+
Expression member_lookup;
member_lookup = MemberLookupFinal (ec, expr_type, expr_type, Identifier, loc);
return DoResolve (ec, right_side);
}
- public override FullNamedExpression ResolveAsTypeStep (EmitContext ec, bool silent)
+ public override FullNamedExpression ResolveAsTypeStep (IResolveContext ec, bool silent)
{
return ResolveNamespaceOrType (ec, silent);
}
- public FullNamedExpression ResolveNamespaceOrType (EmitContext ec, bool silent)
+ public FullNamedExpression ResolveNamespaceOrType (IResolveContext rc, bool silent)
{
- FullNamedExpression new_expr = expr.ResolveAsTypeStep (ec, silent);
+ FullNamedExpression new_expr = expr.ResolveAsTypeStep (rc, silent);
if (new_expr == null)
return null;
if (new_expr is Namespace) {
Namespace ns = (Namespace) new_expr;
- FullNamedExpression retval = ns.Lookup (ec.DeclSpace, Identifier, loc);
+ FullNamedExpression retval = ns.Lookup (rc.DeclContainer, Identifier, loc);
if (!silent && retval == null)
Report.Error (234, loc, "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?",
Identifier, ns.FullName);
return null;
}
- Expression member_lookup = MemberLookup (ec, expr_type, expr_type, Identifier, loc);
+ Expression member_lookup = MemberLookup (rc.DeclContainer.TypeBuilder, expr_type, expr_type, Identifier, loc);
if (member_lookup == null) {
int errors = Report.Errors;
- MemberLookupFailed (ec, expr_type, expr_type, Identifier, null, false, loc);
+ MemberLookupFailed (rc.DeclContainer.TypeBuilder, expr_type, expr_type, Identifier, null, false, loc);
if (!silent && errors == Report.Errors) {
Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'",
}
if (!(member_lookup is TypeExpr)) {
- new_expr.Error_UnexpectedKind (ec, "type", loc);
+ new_expr.Error_UnexpectedKind (rc.DeclContainer, "type", loc);
return null;
}
- member_lookup = member_lookup.Resolve (ec, ResolveFlags.Type);
+ member_lookup = member_lookup.ResolveAsTypeTerminal (rc, silent);
return (member_lookup as TypeExpr);
}
public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
+ if (right_side == EmptyExpression.OutAccess) {
+ Report.Error (206, loc, "A property or indexer `{0}' may not be passed as an out or ref parameter",
+ GetSignatureForError ());
+ return null;
+ }
+
+ // if the indexer returns a value type, and we try to set a field in it
+ if (right_side == EmptyExpression.LValueMemberAccess) {
+ Report.Error (1612, loc, "Cannot modify the return value of `{0}' because it is not a variable",
+ GetSignatureForError ());
+ return null;
+ }
+
ArrayList AllSetters = new ArrayList();
if (!CommonResolve (ec))
return null;
{
Emit (ec, false);
}
+
+ public override string GetSignatureForError ()
+ {
+ // FIXME: print the argument list of the indexer
+ return instance_expr.GetSignatureForError () + ".this[...]";
+ }
}
/// <summary>
return null;
}
- member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type, member,
+ member_lookup = MemberLookup (ec.ContainerType, null, base_type, member,
AllMemberTypes, AllBindingFlags, loc);
if (member_lookup == null) {
- MemberLookupFailed (ec, base_type, base_type, member, null, true, loc);
+ MemberLookupFailed (ec.ContainerType, base_type, base_type, member, null, true, loc);
return null;
}
public class EmptyExpression : Expression {
public static readonly EmptyExpression Null = new EmptyExpression ();
+ public static readonly EmptyExpression OutAccess = new EmptyExpression ();
+ public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression ();
+
static EmptyExpression temp = new EmptyExpression ();
public static EmptyExpression Grab ()
{
loc = l;
}
- public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+ public override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
{
TypeExpr lexpr = left.ResolveAsTypeTerminal (ec, false);
if (lexpr == null)
return null;
- bool old = ec.TestObsoleteMethodUsage;
- ec.TestObsoleteMethodUsage = false;
Type ltype = lexpr.ResolveType (ec);
- ec.TestObsoleteMethodUsage = old;
-
if ((ltype == TypeManager.void_type) && (dim != "*")) {
Report.Error (1547, Location,
"Keyword 'void' cannot be used in this context");
throw new InternalErrorException ("Couldn't create computed type " + ltype + dim);
}
- if (!ec.InUnsafe && type.IsPointer){
+ if (type.IsPointer && !ec.IsInUnsafeScope){
UnsafeError (loc);
return null;
}
}
public override string Name {
- get {
- return left + dim;
- }
+ get { return left + dim; }
}
public override string FullName {
- get {
- return type.FullName;
- }
+ get { return type.FullName; }
+ }
+
+ public override string GetSignatureForError ()
+ {
+ return left.GetSignatureForError () + dim;
}
}