return null;
}
+ //
+ // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with
+ // same name exists or as a keyword when no type was found
+ //
+ public virtual TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent)
+ {
+ return ResolveAsTypeTerminal (rc, silent);
+ }
+
//
// This is used to resolve the expression as a type, a null
// value will be returned if the expression is not a type
if (te == null)
return null;
- if (!silent) {
+ if (!silent) { // && !(te is TypeParameterExpr)) {
ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (te.Type);
if (obsolete_attr != null && !ec.IsInObsoleteScope) {
AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location);
public static void Error_InvalidExpressionStatement (Location loc)
{
- Report.Error (201, loc, "Only assignment, call, increment, decrement and new object " +
+ Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " +
"expressions can be used as a statement");
}
public virtual void Error_ValueCannotBeConverted (EmitContext ec, Location loc, Type target, bool expl)
{
+ // The error was already reported as CS1660
+ if (type == TypeManager.anonymous_method_type)
+ return;
+
if (Type.FullName == target.FullName){
Report.ExtraInformation (loc,
String.Format (
if (expl) {
Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
- GetSignatureForError (), TypeManager.CSharpName (target));
+ TypeManager.CSharpName (type), TypeManager.CSharpName (target));
return;
}
return;
}
- Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",
- Type == TypeManager.anonymous_method_type ?
- "anonymous method" : "`" + GetSignatureForError () + "'",
+ Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'",
+ TypeManager.CSharpName (type),
TypeManager.CSharpName (target));
}
+ protected void Error_VariableIsUsedBeforeItIsDeclared (string name)
+ {
+ Report.Error (841, loc, "The variable `{0}' cannot be used before it is declared",
+ name);
+ }
+
+ protected virtual void Error_TypeDoesNotContainDefinition (Type type, string name)
+ {
+ Error_TypeDoesNotContainDefinition (loc, type, name);
+ }
+
public static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)
{
+ Report.SymbolRelatedToPreviousError (type);
Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",
TypeManager.CSharpName (type), name);
}
return ResolveFlags.VariableOrValue;
default:
- throw new Exception ("Expression " + GetType () +
- " ExprClass is Invalid after resolve");
+ throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve");
}
}
}
if (mi.Length > 1) {
bool is_interface = qualifier_type != null && qualifier_type.IsInterface;
- MemberInfo non_method = null;
ArrayList methods = new ArrayList (2);
+ ArrayList non_methods = null;
foreach (MemberInfo m in mi) {
if (m is MethodBase) {
continue;
}
- if (non_method == null) {
- non_method = m;
+ if (non_methods == null) {
+ non_methods = new ArrayList (2);
+ non_methods.Add (m);
continue;
}
- Report.SymbolRelatedToPreviousError (m);
- Report.SymbolRelatedToPreviousError (non_method);
- Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
- TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (non_method));
- return null;
+ foreach (MemberInfo n_m in non_methods) {
+ if (m.DeclaringType.IsInterface && TypeManager.ImplementsInterface (m.DeclaringType, n_m.DeclaringType))
+ continue;
+
+ Report.SymbolRelatedToPreviousError (m);
+ Report.Error (229, loc, "Ambiguity between `{0}' and `{1}'",
+ TypeManager.GetFullNameSignature (m), TypeManager.GetFullNameSignature (n_m));
+ return null;
+ }
}
if (methods.Count == 0)
- return null;
+ return ExprClassFromMemberInfo (container_type, (MemberInfo)non_methods [0], loc);
- if (non_method != null) {
+ if (non_methods != null) {
MethodBase method = (MethodBase) methods [0];
-
+ MemberInfo non_method = (MemberInfo) non_methods [0];
if (method.DeclaringType == non_method.DeclaringType) {
// Cannot happen with C# code, but is valid in IL
Report.SymbolRelatedToPreviousError (method);
}
}
- return new MethodGroupExpr (methods, loc);
+ return new MethodGroupExpr (methods, queried_type, loc);
}
if (mi [0] is MethodBase)
- return new MethodGroupExpr (mi, loc);
+ return new MethodGroupExpr (mi, queried_type, loc);
return ExprClassFromMemberInfo (container_type, mi [0], loc);
}
name, AllMemberTypes, AllBindingFlags, loc);
}
- public static Expression MethodLookup (Type container_type, Type queried_type,
+ public static MethodGroupExpr MethodLookup (Type container_type, Type queried_type,
string name, Location loc)
{
- return MemberLookup (container_type, null, queried_type, name,
+ return (MethodGroupExpr)MemberLookup (container_type, null, queried_type, name,
MemberTypes.Method, AllBindingFlags, loc);
}
/// look for private members and display a useful debugging message if we
/// find it.
/// </summary>
- public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
- Type queried_type, string name, Location loc)
- {
- return MemberLookupFinal (ec, qualifier_type, queried_type, name,
- AllMemberTypes, AllBindingFlags, loc);
- }
-
- public static Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
+ protected Expression MemberLookupFinal (EmitContext ec, Type qualifier_type,
Type queried_type, string name,
MemberTypes mt, BindingFlags bf,
Location loc)
e = MemberLookup (ec.ContainerType, qualifier_type, queried_type, name, mt, bf, loc);
- if (e == null && errors == Report.Errors)
- // No errors were reported by MemberLookup, but there was an error.
- MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type, name, null, true, loc);
+ if (e != null || errors != Report.Errors)
+ return e;
- return e;
+ // No errors were reported by MemberLookup, but there was an error.
+ return Error_MemberLookupFailed (ec.ContainerType, qualifier_type, queried_type,
+ name, null, mt, bf);
}
- public static void MemberLookupFailed (Type container_type, Type qualifier_type,
- Type queried_type, string name,
- string class_name, bool complain_if_none_found,
- Location loc)
+ protected virtual Expression Error_MemberLookupFailed (Type container_type, Type qualifier_type,
+ Type queried_type, string name, string class_name,
+ MemberTypes mt, BindingFlags bf)
{
if (almostMatchedMembers.Count != 0) {
for (int i = 0; i < almostMatchedMembers.Count; ++i) {
}
}
almostMatchedMembers.Clear ();
- return;
+ return null;
}
MemberInfo[] lookup = null;
class_name = "global::";
} else {
lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
- AllMemberTypes, AllBindingFlags |
- BindingFlags.NonPublic, name, null);
+ mt, (bf & ~BindingFlags.Public) | BindingFlags.NonPublic,
+ name, null);
+
+ if (lookup != null) {
+ Report.SymbolRelatedToPreviousError (lookup [0]);
+ ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
+ return Error_MemberLookupFailed (lookup);
+ }
+
+ lookup = TypeManager.MemberLookup (queried_type, null, queried_type,
+ AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic,
+ name, null);
}
if (lookup == null) {
- if (!complain_if_none_found)
- return;
-
- if (class_name != null)
- Report.Error (103, loc, "The name `{0}' does not exist in the context of `{1}'",
- name, class_name);
- else
- Error_TypeDoesNotContainDefinition (loc, queried_type, name);
- return;
+ if (class_name != null) {
+ Report.Error (103, loc, "The name `{0}' does not exist in the current context",
+ name);
+ } else {
+ Error_TypeDoesNotContainDefinition (queried_type, name);
+ }
+ return null;
}
if (TypeManager.MemberLookup (queried_type, null, queried_type,
"requires {1} type arguments",
TypeManager.CSharpName (t),
TypeManager.GetNumberOfTypeArguments (t).ToString ());
- return;
+ return null;
}
}
- MemberList ml = TypeManager.FindMembers (queried_type, MemberTypes.Constructor,
- BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly, null, null);
- if (name == ".ctor" && ml.Count == 0)
- {
- Report.Error (143, loc, "The type `{0}' has no constructors defined", TypeManager.CSharpName (queried_type));
- return;
+ return Error_MemberLookupFailed (lookup);
+ }
+
+ protected virtual Expression Error_MemberLookupFailed (MemberInfo[] members)
+ {
+ for (int i = 0; i < members.Length; ++i) {
+ if (!(members [i] is MethodBase))
+ return null;
}
- Report.SymbolRelatedToPreviousError (lookup [0]);
- ErrorIsInaccesible (loc, TypeManager.GetFullNameSignature (lookup [0]));
+ // By default propagate the closest candidates upwards
+ return new MethodGroupExpr (members, type, loc);
}
/// <summary>
static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
{
- MethodBase method;
- Expression operator_group;
+ MethodGroupExpr operator_group;
#if GMCS_SOURCE
if (TypeManager.IsNullableType (e.Type))
return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
#endif
- operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc);
+ operator_group = MethodLookup (ec.ContainerType, e.Type, is_true ? "op_True" : "op_False", loc) as MethodGroupExpr;
if (operator_group == null)
return null;
- ArrayList arguments = new ArrayList ();
+ ArrayList arguments = new ArrayList (1);
arguments.Add (new Argument (e, Argument.AType.Expression));
- method = Invocation.OverloadResolve (
- ec, (MethodGroupExpr) operator_group, arguments, false, loc);
+ operator_group = operator_group.OverloadResolve (
+ ec, arguments, false, loc);
- if (method == null)
+ if (operator_group == null)
return null;
- return new StaticCallExpr ((MethodInfo) method, arguments, loc);
+ return new StaticCallExpr ((MethodInfo) operator_group, arguments, loc);
}
/// <summary>
return target;
}
-
+
+ //
+ // Derived classes implement this method by cloning the fields that
+ // could become altered during the Resolve stage
+ //
+ // Only expressions that are created for the parser need to implement
+ // this.
+ //
+ protected virtual void CloneTo (CloneContext clonectx, Expression target)
+ {
+ throw new NotImplementedException (
+ String.Format (
+ "CloneTo not implemented for expression {0}", this.GetType ()));
+ }
+
+ //
+ // Clones an expression created by the parser.
+ //
+ // We only support expressions created by the parser so far, not
+ // expressions that have been resolved (many more classes would need
+ // to implement CloneTo).
+ //
+ // This infrastructure is here merely for Lambda expressions which
+ // compile the same code using different type values for the same
+ // arguments to find the correct overload
+ //
+ public Expression Clone (CloneContext clonectx)
+ {
+ Expression cloned = (Expression) MemberwiseClone ();
+ CloneTo (clonectx, cloned);
+
+ return cloned;
+ }
}
/// <summary>
/// would be "unsigned int".
///
/// </summary>
- public class EmptyCast : Expression {
- protected readonly Expression child;
+ public class EmptyCast : Expression
+ {
+ protected Expression child;
- public EmptyCast (Expression child, Type return_type)
+ protected EmptyCast (Expression child, Type return_type)
{
eclass = child.eclass;
loc = child.Location;
type = return_type;
this.child = child;
}
+
+ public static Expression Create (Expression child, Type type)
+ {
+ Constant c = child as Constant;
+ if (c != null)
+ return new EmptyConstantCast (c, type);
+
+ return new EmptyCast (child, type);
+ }
public override Expression DoResolve (EmitContext ec)
{
return child.GetAttributableValue (valueType, out value);
}
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ EmptyCast target = (EmptyCast) t;
+
+ target.child = child.Clone (clonectx);
+ }
}
/// <summary>
get { return child.IsNegative; }
}
+ public override bool IsZeroInteger {
+ get { return child.IsZeroInteger; }
+ }
+
public override void Emit (EmitContext ec)
{
child.Emit (ec);
public override Constant ConvertImplicitly (Type type)
{
- if (Type == type) {
+ Type this_type = TypeManager.DropGenericTypeArguments (Type);
+ type = TypeManager.DropGenericTypeArguments (type);
+
+ if (this_type == type) {
// This is workaround of mono bug. It can be removed when the latest corlib spreads enough
if (TypeManager.IsEnumType (type.UnderlyingSystemType))
return this;
- if (type.UnderlyingSystemType != Child.Type)
+ Type child_type = TypeManager.DropGenericTypeArguments (Child.Type);
+ if (type.UnderlyingSystemType != child_type)
Child = Child.ConvertImplicitly (type.UnderlyingSystemType);
return this;
}
/// of a dotted-name.
/// </summary>
public class SimpleName : Expression {
- public string Name;
+ public readonly string Name;
public readonly TypeArguments Arguments;
bool in_transit;
public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
{
- if (ec.IsFieldInitializer)
+ if (ec.IsInFieldInitializer)
Report.Error (236, l,
"A field initializer cannot reference the nonstatic field, method, or property `{0}'",
name);
FullNamedExpression ResolveNested (IResolveContext ec, Type t)
{
- if (!TypeManager.IsGenericTypeDefinition (t))
+ if (!TypeManager.IsGenericTypeDefinition (t) && !TypeManager.IsGenericType (t))
return null;
DeclSpace ds = ec.DeclContainer;
if (silent || errors != Report.Errors)
return null;
+ Error_TypeOrNamespaceNotFound (ec);
+ return null;
+ }
+
+ protected virtual void Error_TypeOrNamespaceNotFound (IResolveContext ec)
+ {
MemberCore mc = ec.DeclContainer.GetDefinition (Name);
if (mc != null) {
Error_UnexpectedKind (ec.DeclContainer, "type", GetMemberType (mc), loc);
- return null;
+ return;
}
string ns = ec.DeclContainer.NamespaceEntry.NS.Name;
Type type = a.GetType (fullname);
if (type != null) {
Report.SymbolRelatedToPreviousError (type);
- Expression.ErrorIsInaccesible (loc, fullname);
- return null;
+ Expression.ErrorIsInaccesible (loc, TypeManager.CSharpName (type));
+ return;
}
}
- Type t = ec.DeclContainer.NamespaceEntry.NS.LookForAnyGenericType (Name);
+ Type t = ec.DeclContainer.LookupAnyGeneric (Name);
if (t != null) {
Namespace.Error_InvalidNumberOfTypeArguments (t, loc);
- return null;
+ return;
}
+ if (Arguments != null) {
+ FullNamedExpression retval = ec.DeclContainer.LookupNamespaceOrType (SimpleName.RemoveGenericArity (Name), loc, true);
+ if (retval != null) {
+ Namespace.Error_TypeArgumentsCannotBeUsed (retval.Type, loc, "type");
+ return;
+ }
+ }
+
NamespaceEntry.Error_NamespaceNotFound (loc, Name);
- return null;
}
// TODO: I am still not convinced about this. If someone else will need it
{
if (in_transit)
return null;
- in_transit = true;
+ in_transit = true;
Expression e = DoSimpleNameResolve (ec, right_side, intermediate);
+ in_transit = false;
+
if (e == null)
return null;
else
return pref.Resolve (ec);
}
+
+ Expression expr = current_block.Toplevel.GetTransparentIdentifier (Name);
+ if (expr != null) {
+ if (right_side != null)
+ return expr.ResolveLValue (ec, right_side, loc);
+ return expr.Resolve (ec);
+ }
}
//
// Stage 2: Lookup members
//
- DeclSpace lookup_ds = ec.DeclContainer;
Type almost_matched_type = null;
ArrayList almost_matched = null;
- do {
+ for (DeclSpace lookup_ds = ec.DeclContainer; lookup_ds != null; lookup_ds = lookup_ds.Parent) {
+ // either RootDeclSpace or GenericMethod
if (lookup_ds.TypeBuilder == null)
- break;
+ continue;
e = MemberLookup (ec.ContainerType, lookup_ds.TypeBuilder, Name, loc);
- if (e != null)
- break;
+ if (e != null) {
+ if (e is PropertyExpr) {
+ // since TypeManager.MemberLookup doesn't know if we're doing a lvalue access or not,
+ // it doesn't know which accessor to check permissions against
+ if (((PropertyExpr) e).IsAccessibleFrom (ec.ContainerType, right_side != null))
+ break;
+ } else if (e is EventExpr) {
+ if (((EventExpr) e).IsAccessibleFrom (ec.ContainerType))
+ break;
+ } else {
+ break;
+ }
+ e = null;
+ }
if (almost_matched == null && almostMatchedMembers.Count > 0) {
almost_matched_type = lookup_ds.TypeBuilder;
almost_matched = (ArrayList) almostMatchedMembers.Clone ();
}
-
- lookup_ds =lookup_ds.Parent;
- } while (lookup_ds != null);
-
- if (e == null && ec.ContainerType != null)
- e = MemberLookup (ec.ContainerType, ec.ContainerType, Name, loc);
+ }
if (e == null) {
if (almost_matched == null && almostMatchedMembers.Count > 0) {
}
if (e == null) {
+ if (current_block != null) {
+ IKnownVariable ikv = current_block.Explicit.GetKnownVariable (Name);
+ if (ikv != null) {
+ LocalInfo li = ikv as LocalInfo;
+ // Supress CS0219 warning
+ if (li != null)
+ li.Used = true;
+
+ Error_VariableIsUsedBeforeItIsDeclared (Name);
+ return null;
+ }
+ }
+
if (almost_matched != null)
almostMatchedMembers = almost_matched;
if (almost_matched_type == null)
almost_matched_type = ec.ContainerType;
- MemberLookupFailed (ec.ContainerType, null, almost_matched_type, ((SimpleName) this).Name, ec.DeclContainer.Name, true, loc);
+ Error_MemberLookupFailed (ec.ContainerType, null, almost_matched_type, Name,
+ ec.DeclContainer.Name, AllMemberTypes, AllBindingFlags);
return null;
}
Expression left;
if (me.IsInstance) {
- if (ec.IsStatic || ec.IsFieldInitializer) {
+ if (ec.IsStatic || ec.IsInFieldInitializer) {
//
// Note that an MemberExpr can be both IsInstance and IsStatic.
// An unresolved MethodGroupExpr can contain both kinds of methods
public override void Emit (EmitContext ec)
{
- //
- // If this is ever reached, then we failed to
- // find the name as a namespace
- //
-
- Error (103, "The name `" + Name +
- "' does not exist in the class `" +
- ec.DeclContainer.Name + "'");
+ throw new InternalErrorException ("The resolve phase was not executed");
}
public override string ToString ()
public override string GetSignatureForError ()
{
+ if (Arguments != null) {
+ return TypeManager.RemoveGenericArity (Name) + "<" +
+ Arguments.GetSignatureForError () + ">";
+ }
+
return Name;
}
+
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ // CloneTo: Nothing, we do not keep any state on this expression
+ }
}
/// <summary>
return this;
}
- static readonly char [] dot_array = { '.' };
- protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+ private class UnexpectedType
{
- // If name is of the form `N.I', first lookup `N', then search a member `I' in it.
- string rest = null;
- string lookup_name = name;
- int pos = name.IndexOf ('.');
- if (pos >= 0) {
- rest = name.Substring (pos + 1);
- lookup_name = name.Substring (0, pos);
- }
-
- FullNamedExpression resolved = RootNamespace.Global.Lookup (ec.DeclContainer, lookup_name, Location.Null);
-
- if (resolved != null && rest != null) {
- // Now handle the rest of the the name.
- string [] elements = rest.Split (dot_array);
- string element;
- int count = elements.Length;
- int i = 0;
- while (i < count && resolved != null && resolved is Namespace) {
- Namespace ns = resolved as Namespace;
- element = elements [i++];
- lookup_name += "." + element;
- resolved = ns.Lookup (ec.DeclContainer, element, Location.Null);
- }
+ }
- if (resolved != null && resolved is TypeExpr) {
- Type t = ((TypeExpr) resolved).Type;
- while (t != null) {
- if (!ec.DeclContainer.CheckAccessLevel (t)) {
- resolved = null;
- lookup_name = t.FullName;
- break;
- }
- if (i == count) {
- type = t;
- return this;
- }
- t = TypeManager.GetNestedType (t, elements [i++]);
+ // This performes recursive type lookup, providing support for generic types.
+ // For example, given the type:
+ //
+ // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]]
+ //
+ // The types will be checked in the following order:
+ // _
+ // System |
+ // System.Collections |
+ // System.Collections.Generic |
+ // _ |
+ // System | recursive call 1 |
+ // System.Int32 _| | main method call
+ // _ |
+ // System | recursive call 2 |
+ // System.String _| |
+ // |
+ // System.Collections.Generic.KeyValuePair`2[[System.Int32],[System.String]] _|
+ //
+ private Type TypeLookup (IResolveContext ec, string name)
+ {
+ int index = 0;
+ int dot = 0;
+ bool done = false;
+ FullNamedExpression resolved = null;
+ Type type = null;
+ Type recursive_type = null;
+ while (index < name.Length) {
+ if (name[index] == '[') {
+ int open = index;
+ int braces = 1;
+ do {
+ index++;
+ if (name[index] == '[')
+ braces++;
+ else if (name[index] == ']')
+ braces--;
+ } while (braces > 0);
+ recursive_type = TypeLookup (ec, name.Substring (open + 1, index - open - 1));
+ if (recursive_type == null || (recursive_type == typeof(UnexpectedType)))
+ return recursive_type;
+ }
+ else {
+ if (name[index] == ',')
+ done = true;
+ else if ((name[index] == '.' && !done) || (index == name.Length && name[0] != '[')) {
+ string substring = name.Substring(dot, index - dot);
+
+ if (resolved == null)
+ resolved = RootNamespace.Global.Lookup (ec.DeclContainer, substring, Location.Null);
+ else if (resolved is Namespace)
+ resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null);
+ else if (type != null)
+ type = TypeManager.GetNestedType (type, substring);
+ else
+ return null;
+
+ if (resolved == null)
+ return null;
+ else if (type == null && resolved is TypeExpr)
+ type = resolved.Type;
+
+ dot = index + 1;
}
}
+ index++;
}
+ if (name[0] != '[') {
+ string substring = name.Substring(dot, index - dot);
- if (resolved == null) {
- NamespaceEntry.Error_NamespaceNotFound (loc, lookup_name);
- return null;
+ if (type != null)
+ return TypeManager.GetNestedType (type, substring);
+
+ if (resolved != null) {
+ resolved = (resolved as Namespace).Lookup (ec.DeclContainer, substring, Location.Null);
+ if (resolved is TypeExpr)
+ return resolved.Type;
+
+ if (resolved == null)
+ return null;
+
+ resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
+ return typeof (UnexpectedType);
+ }
+ else
+ return null;
+ }
+ else
+ return recursive_type;
}
- if (!(resolved is TypeExpr)) {
- resolved.Error_UnexpectedKind (ec.DeclContainer, "type", loc);
+ protected override TypeExpr DoResolveAsTypeStep (IResolveContext ec)
+ {
+ Type t = TypeLookup (ec, name);
+ if (t == null) {
+ NamespaceEntry.Error_NamespaceNotFound (loc, name);
return null;
}
-
- type = resolved.Type;
+ if (t == typeof(UnexpectedType))
+ return null;
+ type = t;
return this;
}
public override string FullName {
get { return name; }
}
+
+ protected override void CloneTo (CloneContext clonectx, Expression target)
+ {
+ // CloneTo: Nothing, we do not keep any state on this expression
+ }
+
+ public override string GetSignatureForError ()
+ {
+ if (type == null)
+ return TypeManager.CSharpName (name);
+
+ return base.GetSignatureForError ();
+ }
}
/// <summary>
//
if (left is TypeExpr) {
+ left = left.ResolveAsTypeTerminal (ec, true);
+ if (left == null)
+ return null;
+
if (!IsStatic) {
SimpleName.Error_ObjectRefRequired (ec, loc, GetSignatureForError ());
return null;
}
}
+ ///
+ /// Represents group of extension methods
+ ///
+ public class ExtensionMethodGroupExpr : MethodGroupExpr
+ {
+ readonly NamespaceEntry namespaceEntry;
+ public Expression ExtensionExpression;
+ Argument extension_argument;
+
+ public ExtensionMethodGroupExpr (ArrayList list, NamespaceEntry n, Type extensionType, Location l)
+ : base (list, extensionType, l)
+ {
+ this.namespaceEntry = n;
+ }
+
+ public override bool IsBase {
+ get { return true; }
+ }
+
+ public override bool IsStatic {
+ get { return true; }
+ }
+
+ public bool IsTopLevel {
+ get { return namespaceEntry == null; }
+ }
+
+ public override void EmitArguments (EmitContext ec, ArrayList arguments)
+ {
+ if (arguments == null)
+ arguments = new ArrayList (1);
+ arguments.Insert (0, extension_argument);
+ base.EmitArguments (ec, arguments);
+ }
+
+ public override void EmitCall (EmitContext ec, ArrayList arguments)
+ {
+ if (arguments == null)
+ arguments = new ArrayList (1);
+ arguments.Insert (0, extension_argument);
+ base.EmitCall (ec, arguments);
+ }
+
+ public override MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList arguments, bool may_fail, Location loc)
+ {
+ if ((ExtensionExpression.eclass & (ExprClass.Value | ExprClass.Variable)) == 0)
+ return base.OverloadResolve (ec, arguments, may_fail, loc);
+
+ if (arguments == null)
+ arguments = new ArrayList (1);
+
+ arguments.Insert (0, new Argument (ExtensionExpression));
+ MethodGroupExpr mg = ResolveOverloadExtensions (ec, arguments, namespaceEntry, loc);
+
+ // Store resolved argument and restore original arguments
+ if (mg != null)
+ ((ExtensionMethodGroupExpr)mg).extension_argument = (Argument)arguments [0];
+ arguments.RemoveAt (0);
+
+ return mg;
+ }
+
+ MethodGroupExpr ResolveOverloadExtensions (EmitContext ec, ArrayList arguments, NamespaceEntry ns, Location loc)
+ {
+ // Use normal resolve rules
+ MethodGroupExpr mg = base.OverloadResolve (ec, arguments, ns != null, loc);
+ if (mg != null)
+ return mg;
+
+ if (ns == null)
+ return null;
+
+ // Search continues
+ ExtensionMethodGroupExpr e = ns.LookupExtensionMethod (type, null, Name);
+ if (e == null)
+ return base.OverloadResolve (ec, arguments, false, loc);
+
+ e.ExtensionExpression = ExtensionExpression;
+ return e.ResolveOverloadExtensions (ec, arguments, e.namespaceEntry, loc);
+ }
+ }
+
/// <summary>
- /// MethodGroup Expression.
- ///
- /// This is a fully resolved expression that evaluates to a type
+ /// MethodGroupExpr represents a group of method candidates which
+ /// can be resolved to the best method overload
/// </summary>
- public class MethodGroupExpr : MemberExpr {
+ public class MethodGroupExpr : MemberExpr
+ {
+ public interface IErrorHandler
+ {
+ bool NoExactMatch (EmitContext ec, MethodBase method);
+ }
+
+ public static IErrorHandler CustomErrorHandler;
public MethodBase [] Methods;
- bool has_type_arguments = false;
- bool identical_type_name = false;
+ MethodBase best_candidate;
+ bool has_type_arguments;
+ bool identical_type_name;
bool is_base;
- public MethodGroupExpr (MemberInfo [] mi, Location l)
+ public MethodGroupExpr (MemberInfo [] mi, Type type, Location l)
+ : this (type, l)
{
Methods = new MethodBase [mi.Length];
mi.CopyTo (Methods, 0);
- eclass = ExprClass.MethodGroup;
-
- // Set the type to something that will never be useful, which will
- // trigger the proper conversions.
- type = typeof (MethodGroupExpr);
- loc = l;
}
- public MethodGroupExpr (ArrayList list, Location l)
+ public MethodGroupExpr (ArrayList list, Type type, Location l)
+ : this (type, l)
{
- Methods = new MethodBase [list.Count];
-
try {
- list.CopyTo (Methods, 0);
+ Methods = (MethodBase[])list.ToArray (typeof (MethodBase));
} catch {
foreach (MemberInfo m in list){
if (!(m is MethodBase)){
throw;
}
- loc = l;
+
+ }
+
+ protected MethodGroupExpr (Type type, Location loc)
+ {
+ this.loc = loc;
eclass = ExprClass.MethodGroup;
- type = TypeManager.object_type;
+ this.type = type;
}
public override Type DeclaringType {
get {
return has_type_arguments;
}
-
- set {
- has_type_arguments = value;
- }
}
public bool IdenticalTypeName {
}
}
- public bool IsBase {
+ public virtual bool IsBase {
get {
return is_base;
}
public override string GetSignatureForError ()
{
+ if (best_candidate != null)
+ return TypeManager.CSharpSignature (best_candidate);
+
return TypeManager.CSharpSignature (Methods [0]);
}
return false;
}
}
-
- public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
- SimpleName original)
- {
- if (!(left is TypeExpr) &&
- original != null && original.IdenticalNameAndTypeName (ec, left, loc))
- IdenticalTypeName = true;
-
- return base.ResolveMemberAccess (ec, left, loc, original);
- }
- override public Expression DoResolve (EmitContext ec)
+ public static explicit operator ConstructorInfo (MethodGroupExpr mg)
{
- if (!IsInstance)
- InstanceExpression = null;
-
- if (InstanceExpression != null) {
- InstanceExpression = InstanceExpression.DoResolve (ec);
- if (InstanceExpression == null)
- return null;
- }
-
- return this;
+ return (ConstructorInfo)mg.best_candidate;
}
- public void ReportUsageError ()
+ public static explicit operator MethodInfo (MethodGroupExpr mg)
{
- Report.Error (654, loc, "Method `" + DeclaringType + "." +
- Name + "()' is referenced without parentheses");
+ return (MethodInfo)mg.best_candidate;
}
- override public void Emit (EmitContext ec)
+ /// <summary>
+ /// Determines "better conversion" as specified in 14.4.2.3
+ ///
+ /// Returns : p if a->p is better,
+ /// q if a->q is better,
+ /// null if neither is better
+ /// </summary>
+ static Type BetterConversion (EmitContext ec, Argument a, Type p, Type q)
{
- ReportUsageError ();
- }
+ Type argument_type = TypeManager.TypeToCoreType (a.Type);
+ Expression argument_expr = a.Expr;
- bool RemoveMethods (bool keep_static)
- {
- ArrayList smethods = new ArrayList ();
+ if (argument_type == null)
+ throw new Exception ("Expression of type " + a.Expr +
+ " does not resolve its type");
- foreach (MethodBase mb in Methods){
- if (mb.IsStatic == keep_static)
- smethods.Add (mb);
- }
+ if (p == null || q == null)
+ throw new InternalErrorException ("BetterConversion Got a null conversion");
- if (smethods.Count == 0)
- return false;
+ if (p == q)
+ return null;
- Methods = new MethodBase [smethods.Count];
- smethods.CopyTo (Methods, 0);
+ if (argument_expr is NullLiteral)
+ {
+ //
+ // 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.
+ //
+ // This follows from the usual rules:
+ // * There is an implicit conversion from 'null' to type 'object'
+ // * There is an implicit conversion from 'null' to any reference type
+ // * There is an implicit conversion from any reference type to type 'object'
+ // * There is no implicit conversion from type 'object' to other reference types
+ // => Conversion of 'null' to a reference type is better than conversion to 'object'
+ //
+ // FIXME: This probably isn't necessary, since the type of a NullLiteral is the
+ // null type. I think it used to be 'object' and thus needed a special
+ // case to avoid the immediately following two checks.
+ //
+ if (!p.IsValueType && q == TypeManager.object_type)
+ return p;
+ if (!q.IsValueType && p == TypeManager.object_type)
+ return q;
+ }
+
+ if (argument_type == p)
+ return p;
+
+ if (argument_type == q)
+ return q;
+
+ Expression p_tmp = new EmptyExpression (p);
+ Expression q_tmp = new EmptyExpression (q);
+
+ bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q);
+ bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p);
+
+ if (p_to_q && !q_to_p)
+ return p;
+
+ if (q_to_p && !p_to_q)
+ return q;
+
+ if (p == TypeManager.sbyte_type)
+ if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
+ q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+ return p;
+ if (q == TypeManager.sbyte_type)
+ if (p == TypeManager.byte_type || p == TypeManager.ushort_type ||
+ p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+ return q;
+
+ if (p == TypeManager.short_type)
+ if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
+ q == TypeManager.uint64_type)
+ return p;
+ if (q == TypeManager.short_type)
+ if (p == TypeManager.ushort_type || p == TypeManager.uint32_type ||
+ p == TypeManager.uint64_type)
+ return q;
+
+ if (p == TypeManager.int32_type)
+ if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
+ return p;
+ if (q == TypeManager.int32_type)
+ if (p == TypeManager.uint32_type || p == TypeManager.uint64_type)
+ return q;
+
+ if (p == TypeManager.int64_type)
+ if (q == TypeManager.uint64_type)
+ return p;
+ if (q == TypeManager.int64_type)
+ if (p == TypeManager.uint64_type)
+ return q;
- return true;
+ return null;
}
-
+
/// <summary>
- /// Removes any instance methods from the MethodGroup, returns
- /// false if the resulting set is empty.
+ /// Determines "Better function" between candidate
+ /// and the current best match
/// </summary>
- public bool RemoveInstanceMethods ()
+ /// <remarks>
+ /// Returns a boolean indicating :
+ /// false if candidate ain't better
+ /// true if candidate is better than the current best match
+ /// </remarks>
+ static bool BetterFunction (EmitContext ec, ArrayList args, int argument_count,
+ MethodBase candidate, bool candidate_params,
+ MethodBase best, bool best_params)
{
- return RemoveMethods (true);
+ ParameterData candidate_pd = TypeManager.GetParameterData (candidate);
+ ParameterData best_pd = TypeManager.GetParameterData (best);
+
+ bool better_at_least_one = false;
+ bool same = true;
+ for (int j = 0, c_idx = 0, b_idx = 0; j < argument_count; ++j, ++c_idx, ++b_idx)
+ {
+ Argument a = (Argument) args [j];
+
+ Type ct = TypeManager.TypeToCoreType (candidate_pd.ParameterType (c_idx));
+ Type bt = TypeManager.TypeToCoreType (best_pd.ParameterType (b_idx));
+
+ if (candidate_params && candidate_pd.ParameterModifier (c_idx) == Parameter.Modifier.PARAMS)
+ {
+ ct = TypeManager.GetElementType (ct);
+ --c_idx;
+ }
+
+ if (best_params && best_pd.ParameterModifier (b_idx) == Parameter.Modifier.PARAMS)
+ {
+ bt = TypeManager.GetElementType (bt);
+ --b_idx;
+ }
+
+ if (ct.Equals (bt))
+ continue;
+
+ same = false;
+ Type better = BetterConversion (ec, a, ct, bt);
+
+ // for each argument, the conversion to 'ct' should be no worse than
+ // the conversion to 'bt'.
+ if (better == bt)
+ return false;
+
+ // for at least one argument, the conversion to 'ct' should be better than
+ // the conversion to 'bt'.
+ if (better == ct)
+ better_at_least_one = true;
+ }
+
+ if (better_at_least_one)
+ return true;
+
+ //
+ // This handles the case
+ //
+ // Add (float f1, float f2, float f3);
+ // Add (params decimal [] foo);
+ //
+ // The call Add (3, 4, 5) should be ambiguous. Without this check, the
+ // first candidate would've chosen as better.
+ //
+ if (!same)
+ return false;
+
+ //
+ // The two methods have equal parameter types. Now apply tie-breaking rules
+ //
+ if (TypeManager.IsGenericMethod (best) && !TypeManager.IsGenericMethod (candidate))
+ return true;
+ if (!TypeManager.IsGenericMethod (best) && TypeManager.IsGenericMethod (candidate))
+ return false;
+
+ //
+ // This handles the following cases:
+ //
+ // Trim () is better than Trim (params char[] chars)
+ // Concat (string s1, string s2, string s3) is better than
+ // Concat (string s1, params string [] srest)
+ // Foo (int, params int [] rest) is better than Foo (params int [] rest)
+ //
+ if (!candidate_params && best_params)
+ return true;
+ if (candidate_params && !best_params)
+ return false;
+
+ int candidate_param_count = candidate_pd.Count;
+ int best_param_count = best_pd.Count;
+
+ if (candidate_param_count != best_param_count)
+ // can only happen if (candidate_params && best_params)
+ return candidate_param_count > best_param_count;
+
+ //
+ // now, both methods have the same number of parameters, and the parameters have the same types
+ // Pick the "more specific" signature
+ //
+
+ MethodBase orig_candidate = TypeManager.DropGenericMethodArguments (candidate);
+ MethodBase orig_best = TypeManager.DropGenericMethodArguments (best);
+
+ ParameterData orig_candidate_pd = TypeManager.GetParameterData (orig_candidate);
+ ParameterData orig_best_pd = TypeManager.GetParameterData (orig_best);
+
+ bool specific_at_least_once = false;
+ for (int j = 0; j < candidate_param_count; ++j)
+ {
+ Type ct = TypeManager.TypeToCoreType (orig_candidate_pd.ParameterType (j));
+ Type bt = TypeManager.TypeToCoreType (orig_best_pd.ParameterType (j));
+ if (ct.Equals (bt))
+ continue;
+ Type specific = MoreSpecific (ct, bt);
+ if (specific == bt)
+ return false;
+ if (specific == ct)
+ specific_at_least_once = true;
+ }
+
+ if (specific_at_least_once)
+ return true;
+
+ // FIXME: handle lifted operators
+ // ...
+
+ return false;
+ }
+
+ public override Expression ResolveMemberAccess (EmitContext ec, Expression left, Location loc,
+ SimpleName original)
+ {
+ if (!(left is TypeExpr) &&
+ original != null && original.IdenticalNameAndTypeName (ec, left, loc))
+ IdenticalTypeName = true;
+
+ return base.ResolveMemberAccess (ec, left, loc, original);
+ }
+
+ override public Expression DoResolve (EmitContext ec)
+ {
+ if (InstanceExpression != null) {
+ InstanceExpression = InstanceExpression.DoResolve (ec);
+ if (InstanceExpression == null)
+ return null;
+ }
+
+ return this;
+ }
+
+ public void ReportUsageError ()
+ {
+ Report.Error (654, loc, "Method `" + DeclaringType + "." +
+ Name + "()' is referenced without parentheses");
+ }
+
+ override public void Emit (EmitContext ec)
+ {
+ ReportUsageError ();
+ }
+
+ public virtual void EmitArguments (EmitContext ec, ArrayList arguments)
+ {
+ Invocation.EmitArguments (ec, best_candidate, arguments, false, null);
+ }
+
+ public virtual void EmitCall (EmitContext ec, ArrayList arguments)
+ {
+ Invocation.EmitCall (ec, IsBase, InstanceExpression, best_candidate, arguments, loc);
+ }
+
+ protected virtual void Error_InvalidArguments (EmitContext ec, Location loc, int idx, MethodBase method,
+ Type delegate_type, Argument a, ParameterData expected_par)
+ {
+ if (a is CollectionElementInitializer.ElementInitializerArgument) {
+ Report.SymbolRelatedToPreviousError (method);
+ if ((expected_par.ParameterModifier (idx) & Parameter.Modifier.ISBYREF) != 0) {
+ Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier",
+ TypeManager.CSharpSignature (method));
+ return;
+ }
+ Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments",
+ TypeManager.CSharpSignature (method));
+ } else if (delegate_type == null) {
+ Report.SymbolRelatedToPreviousError (method);
+ Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments",
+ TypeManager.CSharpSignature (method));
+ } else
+ Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments",
+ TypeManager.CSharpName (delegate_type));
+
+ Parameter.Modifier mod = expected_par.ParameterModifier (idx);
+
+ string index = (idx + 1).ToString ();
+ if ((mod & Parameter.Modifier.ISBYREF) != (a.Modifier & Parameter.Modifier.ISBYREF) ||
+ (mod & Parameter.Modifier.ISBYREF) != 0) {
+ if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) == 0)
+ Report.Error (1615, loc, "Argument `{0}' should not be passed with the `{1}' keyword",
+ index, Parameter.GetModifierSignature (a.Modifier));
+ else
+ Report.Error (1620, loc, "Argument `{0}' must be passed with the `{1}' keyword",
+ index, Parameter.GetModifierSignature (mod));
+ } else {
+ string p1 = Argument.FullDesc (a);
+ string p2 = TypeManager.CSharpName (expected_par.ParameterType (idx));
+
+ if (p1 == p2) {
+ Report.ExtraInformation (loc, "(equally named types possibly from different assemblies in previous ");
+ Report.SymbolRelatedToPreviousError (a.Expr.Type);
+ Report.SymbolRelatedToPreviousError (expected_par.ParameterType (idx));
+ }
+ Report.Error (1503, loc, "Argument {0}: Cannot convert type `{1}' to `{2}'", index, p1, p2);
+ }
+ }
+
+ protected virtual int GetApplicableParametersCount (MethodBase method, ParameterData parameters)
+ {
+ return parameters.Count;
+ }
+
+ public static bool IsAncestralType (Type first_type, Type second_type)
+ {
+ return first_type != second_type &&
+ (TypeManager.IsSubclassOf (second_type, first_type) ||
+ TypeManager.ImplementsInterface (second_type, first_type));
+ }
+
+ ///
+ /// Determines if the candidate method is applicable (section 14.4.2.1)
+ /// to the given set of arguments
+ /// A return value rates candidate method compatibility,
+ /// 0 = the best, int.MaxValue = the worst
+ ///
+ public int IsApplicable (EmitContext ec,
+ ArrayList arguments, int arg_count, ref MethodBase method)
+ {
+ MethodBase candidate = method;
+
+ ParameterData pd = TypeManager.GetParameterData (candidate);
+ int param_count = GetApplicableParametersCount (candidate, pd);
+
+ if (arg_count != param_count)
+ return int.MaxValue;
+
+ //
+ // 1. Infer type arguments for generic method
+ //
+#if GMCS_SOURCE
+ if (!HasTypeArguments && TypeManager.IsGenericMethod (method)) {
+ int score = TypeManager.InferTypeArguments (ec, arguments, ref candidate);
+ if (score != 0)
+ return --score;
+
+ if (TypeManager.IsGenericMethodDefinition (candidate))
+ throw new InternalErrorException ("a generic method definition took part in overload resolution");
+
+ pd = TypeManager.GetParameterData (candidate);
+ }
+#endif
+
+ //
+ // 2. Each argument has to be implicitly converible to method parameter
+ //
+ for (int i = arg_count; i > 0; ) {
+ i--;
+
+ Argument a = (Argument) arguments [i];
+
+ Parameter.Modifier a_mod = a.Modifier &
+ ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
+
+ Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+ ~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK | Parameter.Modifier.PARAMS);
+
+ Type pt = pd.ParameterType (i);
+
+ // FIXME: Kill this abomination (EmitContext.TempEc)
+ EmitContext prevec = EmitContext.TempEc;
+ EmitContext.TempEc = ec;
+ try {
+ if (pt.IsByRef)
+ pt = pt.GetElementType ();
+
+ if (!Convert.ImplicitConversionExists (ec, a.Expr, pt))
+ return ++i * 2;
+
+ if (a_mod != p_mod)
+ return ++i * 2 - 1;
+
+ } finally {
+ EmitContext.TempEc = prevec;
+ }
+ }
+
+ method = candidate;
+ return 0;
+ }
+
+ public static bool IsOverride (MethodBase cand_method, MethodBase base_method)
+ {
+ if (!IsAncestralType (base_method.DeclaringType, cand_method.DeclaringType))
+ return false;
+
+ ParameterData cand_pd = TypeManager.GetParameterData (cand_method);
+ ParameterData base_pd = TypeManager.GetParameterData (base_method);
+
+ if (cand_pd.Count != base_pd.Count)
+ return false;
+
+ for (int j = 0; j < cand_pd.Count; ++j)
+ {
+ Parameter.Modifier cm = cand_pd.ParameterModifier (j);
+ Parameter.Modifier bm = base_pd.ParameterModifier (j);
+ Type ct = TypeManager.TypeToCoreType (cand_pd.ParameterType (j));
+ Type bt = TypeManager.TypeToCoreType (base_pd.ParameterType (j));
+
+ if (cm != bm || ct != bt)
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool IsParamsMethodApplicable (EmitContext ec,
+ ArrayList arguments, int arg_count,
+ ref MethodBase candidate)
+ {
+ return IsParamsMethodApplicable (
+ ec, arguments, arg_count, false, ref candidate) ||
+ IsParamsMethodApplicable (
+ ec, arguments, arg_count, true, ref candidate);
+
+
+ }
+
+ bool IsParamsMethodApplicable (EmitContext ec,
+ ArrayList arguments, int arg_count,
+ bool do_varargs, ref MethodBase candidate)
+ {
+#if GMCS_SOURCE
+ if (!HasTypeArguments &&
+ !TypeManager.InferParamsTypeArguments (ec, arguments, ref candidate))
+ return false;
+
+ if (TypeManager.IsGenericMethodDefinition (candidate))
+ throw new InternalErrorException ("a generic method definition took part in overload resolution");
+#endif
+
+ return IsParamsMethodApplicable (
+ ec, arguments, arg_count, candidate, do_varargs);
}
/// <summary>
- /// Removes any static methods from the MethodGroup, returns
- /// false if the resulting set is empty.
+ /// Determines if the candidate method, if a params method, is applicable
+ /// in its expanded form to the given set of arguments
/// </summary>
- public bool RemoveStaticMethods ()
+ bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments,
+ int arg_count, MethodBase candidate,
+ bool do_varargs)
{
- return RemoveMethods (false);
+ ParameterData pd = TypeManager.GetParameterData (candidate);
+ int pd_count = GetApplicableParametersCount (candidate, pd);
+ if (pd_count == 0)
+ return false;
+
+ int count = pd_count - 1;
+ if (do_varargs) {
+ if (pd.ParameterModifier (count) != Parameter.Modifier.ARGLIST)
+ return false;
+ if (pd_count != arg_count)
+ return false;
+
+ if (!(((Argument) arguments [count]).Expr is Arglist))
+ return false;
+ --pd_count;
+ } else {
+ if (!pd.HasParams)
+ return false;
+ }
+
+ if (count > arg_count)
+ return false;
+
+ if (pd_count == 1 && arg_count == 0)
+ return true;
+
+ //
+ // If we have come this far, the case which
+ // remains is when the number of parameters is
+ // less than or equal to the argument count.
+ //
+ int argument_index = 0;
+ Argument a;
+ for (int i = 0; i < pd_count; ++i) {
+
+ if ((pd.ParameterModifier (i) & Parameter.Modifier.PARAMS) != 0) {
+ Type element_type = TypeManager.GetElementType (pd.ParameterType (i));
+ int params_args_count = arg_count - pd_count;
+ if (params_args_count < 0)
+ continue;
+
+ do {
+ a = (Argument) arguments [argument_index++];
+
+ if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
+ return false;
+ } while (params_args_count-- > 0);
+ continue;
+ }
+
+ a = (Argument) arguments [argument_index++];
+
+ Parameter.Modifier a_mod = a.Modifier &
+ (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
+ Parameter.Modifier p_mod = pd.ParameterModifier (i) &
+ (unchecked (~(Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK)));
+
+ if (a_mod == p_mod) {
+
+ if (a_mod == Parameter.Modifier.NONE)
+ if (!Convert.ImplicitConversionExists (ec,
+ a.Expr,
+ pd.ParameterType (i)))
+ return false;
+
+ if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
+ Type pt = pd.ParameterType (i);
+
+ if (!pt.IsByRef)
+ pt = TypeManager.GetReferenceType (pt);
+
+ if (pt != a.Type)
+ return false;
+ }
+ } else
+ return false;
+
+ }
+
+ return true;
+ }
+
+ public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
+ {
+ MemberInfo [] miset;
+ MethodGroupExpr union;
+
+ if (mg1 == null) {
+ if (mg2 == null)
+ return null;
+ return (MethodGroupExpr) mg2;
+ } else {
+ if (mg2 == null)
+ return (MethodGroupExpr) mg1;
+ }
+
+ MethodGroupExpr left_set = null, right_set = null;
+ int length1 = 0, length2 = 0;
+
+ left_set = (MethodGroupExpr) mg1;
+ length1 = left_set.Methods.Length;
+
+ right_set = (MethodGroupExpr) mg2;
+ length2 = right_set.Methods.Length;
+
+ ArrayList common = new ArrayList ();
+
+ foreach (MethodBase r in right_set.Methods){
+ if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
+ common.Add (r);
+ }
+
+ miset = new MemberInfo [length1 + length2 - common.Count];
+ left_set.Methods.CopyTo (miset, 0);
+
+ int k = length1;
+
+ foreach (MethodBase r in right_set.Methods) {
+ if (!common.Contains (r))
+ miset [k++] = r;
+ }
+
+ union = new MethodGroupExpr (miset, mg1.Type, loc);
+
+ return union;
+ }
+
+ static Type MoreSpecific (Type p, Type q)
+ {
+ if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q))
+ return q;
+ if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q))
+ return p;
+
+ if (TypeManager.HasElementType (p))
+ {
+ Type pe = TypeManager.GetElementType (p);
+ Type qe = TypeManager.GetElementType (q);
+ Type specific = MoreSpecific (pe, qe);
+ if (specific == pe)
+ return p;
+ if (specific == qe)
+ return q;
+ }
+ else if (TypeManager.IsGenericType (p))
+ {
+ Type[] pargs = TypeManager.GetTypeArguments (p);
+ Type[] qargs = TypeManager.GetTypeArguments (q);
+
+ bool p_specific_at_least_once = false;
+ bool q_specific_at_least_once = false;
+
+ for (int i = 0; i < pargs.Length; i++)
+ {
+ Type specific = MoreSpecific (pargs [i], qargs [i]);
+ if (specific == pargs [i])
+ p_specific_at_least_once = true;
+ if (specific == qargs [i])
+ q_specific_at_least_once = true;
+ }
+
+ if (p_specific_at_least_once && !q_specific_at_least_once)
+ return p;
+ if (!p_specific_at_least_once && q_specific_at_least_once)
+ return q;
+ }
+
+ return null;
}
+ /// <summary>
+ /// Find the Applicable Function Members (7.4.2.1)
+ ///
+ /// me: Method Group expression with the members to select.
+ /// it might contain constructors or methods (or anything
+ /// that maps to a method).
+ ///
+ /// Arguments: ArrayList containing resolved Argument objects.
+ ///
+ /// loc: The location if we want an error to be reported, or a Null
+ /// location for "probing" purposes.
+ ///
+ /// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
+ /// that is the best match of me on Arguments.
+ ///
+ /// </summary>
+ public virtual MethodGroupExpr OverloadResolve (EmitContext ec, ArrayList Arguments,
+ bool may_fail, Location loc)
+ {
+ bool method_params = false;
+ Type applicable_type = null;
+ int arg_count = 0;
+ ArrayList candidates = new ArrayList (2);
+ ArrayList candidate_overrides = null;
+
+ //
+ // Used to keep a map between the candidate
+ // and whether it is being considered in its
+ // normal or expanded form
+ //
+ // false is normal form, true is expanded form
+ //
+ Hashtable candidate_to_form = null;
+
+ if (Arguments != null)
+ arg_count = Arguments.Count;
+
+ if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
+ if (!may_fail)
+ Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
+ return null;
+ }
+
+ int nmethods = Methods.Length;
+
+ if (!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 GMCS_SOURCE
+ Type [] gen_args = null;
+ if (m.IsGenericMethod && !m.IsGenericMethodDefinition)
+ gen_args = m.GetGenericArguments ();
+#endif
+ if (TypeManager.IsOverride (m)) {
+ if (candidate_overrides == null)
+ candidate_overrides = new ArrayList ();
+ candidate_overrides.Add (m);
+ m = TypeManager.TryGetBaseDefinition (m);
+#if GMCS_SOURCE
+ if (m != null && gen_args != null) {
+ if (!m.IsGenericMethodDefinition)
+ throw new InternalErrorException ("GetBaseDefinition didn't return a GenericMethodDefinition");
+ m = ((MethodInfo) m).MakeGenericMethod (gen_args);
+ }
+#endif
+ }
+ if (m != null)
+ Methods [j++] = m;
+ }
+ nmethods = j;
+ }
+
+ //
+ // Enable message recording, it's used mainly by lambda expressions
+ //
+ Report.IMessageRecorder msg_recorder = new Report.MessageRecorder ();
+ Report.IMessageRecorder prev_recorder = Report.SetMessageRecorder (msg_recorder);
+
+ //
+ // First we construct the set of applicable methods
+ //
+ bool is_sorted = true;
+ int best_candidate_rate = int.MaxValue;
+ 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))
+ continue;
+
+ //
+ // Check if candidate is applicable (section 14.4.2.1)
+ // Is candidate applicable in normal form?
+ //
+ int candidate_rate = IsApplicable (ec, Arguments, arg_count, ref Methods [i]);
+
+ if (candidate_rate != 0 && IsParamsMethodApplicable (ec, Arguments, arg_count, ref Methods [i])) {
+ MethodBase candidate = Methods [i];
+ if (candidate_to_form == null)
+ candidate_to_form = new PtrHashtable ();
+ candidate_to_form [candidate] = candidate;
+ // Candidate is applicable in expanded form
+ candidate_rate = 0;
+ }
+
+ if (candidate_rate < best_candidate_rate) {
+ best_candidate_rate = candidate_rate;
+ best_candidate = Methods [i];
+ }
+
+ if (candidate_rate != 0) {
+ if (msg_recorder != null)
+ msg_recorder.EndSession ();
+ continue;
+ }
+
+ msg_recorder = null;
+
+ candidates.Add (Methods [i]);
+
+ if (applicable_type == null)
+ applicable_type = decl_type;
+ else if (applicable_type != decl_type) {
+ is_sorted = false;
+ if (IsAncestralType (applicable_type, decl_type))
+ applicable_type = decl_type;
+ }
+ }
+
+ Report.SetMessageRecorder (prev_recorder);
+ if (msg_recorder != null && msg_recorder.PrintMessages ())
+ return null;
+
+ int candidate_top = candidates.Count;
+
+ if (applicable_type == null) {
+ if (ec.IsInProbingMode || may_fail)
+ return null;
+
+ //
+ // Okay so we have failed to find exact match so we
+ // return error info about the closest match
+ //
+ if (best_candidate != null) {
+ if (CustomErrorHandler != null) {
+ if (CustomErrorHandler.NoExactMatch (ec, best_candidate))
+ return null;
+ }
+
+ if (TypeManager.IsGenericMethod (best_candidate)) {
+ Report.Error (411, loc,
+ "The type arguments for method `{0}' cannot be inferred from " +
+ "the usage. Try specifying the type arguments explicitly",
+ TypeManager.CSharpSignature (best_candidate));
+ } else {
+ VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate, false, null, may_fail, loc);
+ }
+
+ return null;
+ }
+
+ if (almostMatchedMembers.Count != 0) {
+ Error_MemberLookupFailed (ec.ContainerType, type, type, ".ctor",
+ null, MemberTypes.Constructor, AllBindingFlags);
+ return null;
+ }
+
+ //
+ // We failed to find any match
+ //
+ if (Name == ConstructorInfo.ConstructorName) {
+ Report.SymbolRelatedToPreviousError (type);
+ Report.Error (1729, loc,
+ "The type `{0}' does not contain a constructor that takes `{1}' arguments",
+ TypeManager.CSharpName (type), arg_count);
+ } else {
+ string report_name = Name;
+ if (report_name == ConstructorInfo.ConstructorName)
+ report_name = TypeManager.CSharpName (DeclaringType);
+
+ Invocation.Error_WrongNumArguments (loc, report_name, arg_count);
+ }
+
+ return null;
+ }
+
+ if (!is_sorted) {
+ //
+ // At this point, applicable_type is _one_ of the most derived types
+ // in the set of types containing the methods in this MethodGroup.
+ // Filter the candidates so that they only contain methods from the
+ // most derived types.
+ //
+
+ int finalized = 0; // Number of finalized candidates
+
+ do {
+ // Invariant: applicable_type is a most derived type
+
+ // We'll try to complete Section 14.5.5.1 for 'applicable_type' by
+ // eliminating all it's base types. At the same time, we'll also move
+ // every unrelated type to the end of the array, and pick the next
+ // 'applicable_type'.
+
+ Type next_applicable_type = null;
+ int j = finalized; // where to put the next finalized candidate
+ int k = finalized; // where to put the next undiscarded candidate
+ for (int i = finalized; i < candidate_top; ++i) {
+ MethodBase candidate = (MethodBase) candidates [i];
+ Type decl_type = candidate.DeclaringType;
+
+ if (decl_type == applicable_type) {
+ candidates [k++] = candidates [j];
+ candidates [j++] = candidates [i];
+ continue;
+ }
+
+ if (IsAncestralType (decl_type, applicable_type))
+ continue;
+
+ if (next_applicable_type != null &&
+ IsAncestralType (decl_type, next_applicable_type))
+ continue;
+
+ candidates [k++] = candidates [i];
+
+ if (next_applicable_type == null ||
+ IsAncestralType (next_applicable_type, decl_type))
+ next_applicable_type = decl_type;
+ }
+
+ applicable_type = next_applicable_type;
+ finalized = j;
+ candidate_top = k;
+ } while (applicable_type != null);
+ }
+
+ //
+ // Now we actually find the best method
+ //
+
+ best_candidate = (MethodBase) candidates [0];
+ method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
+ for (int ix = 1; ix < candidate_top; ix++) {
+ MethodBase candidate = (MethodBase) candidates [ix];
+
+ if (candidate == best_candidate)
+ continue;
+
+ bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+
+ if (BetterFunction (ec, Arguments, arg_count,
+ candidate, cand_params,
+ best_candidate, method_params)) {
+ best_candidate = candidate;
+ method_params = cand_params;
+ }
+ }
+ //
+ // Now check that there are no ambiguities i.e the selected method
+ // should be better than all the others
+ //
+ MethodBase ambiguous = null;
+ for (int ix = 0; ix < candidate_top; ix++) {
+ MethodBase candidate = (MethodBase) candidates [ix];
+
+ if (candidate == best_candidate)
+ continue;
+
+ bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
+ if (!BetterFunction (ec, Arguments, arg_count,
+ best_candidate, method_params,
+ candidate, cand_params))
+ {
+ if (!may_fail)
+ Report.SymbolRelatedToPreviousError (candidate);
+ ambiguous = candidate;
+ }
+ }
+
+ if (ambiguous != null) {
+ Report.SymbolRelatedToPreviousError (best_candidate);
+ Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'",
+ TypeManager.CSharpSignature (ambiguous), TypeManager.CSharpSignature (best_candidate));
+ return this;
+ }
+
+ //
+ // If the method is a virtual function, pick an override closer to the LHS type.
+ //
+ if (!IsBase && best_candidate.IsVirtual) {
+ if (TypeManager.IsOverride (best_candidate))
+ throw new InternalErrorException (
+ "Should not happen. An 'override' method took part in overload resolution: " + best_candidate);
+
+ if (candidate_overrides != null)
+ foreach (MethodBase candidate in candidate_overrides) {
+ if (IsOverride (candidate, best_candidate))
+ best_candidate = candidate;
+ }
+ }
+
+ // We can stop here when probing is on
+ if (ec.IsInProbingMode)
+ return this;
+
+ //
+ // And now check if the arguments are all
+ // compatible, perform conversions if
+ // necessary etc. and return if everything is
+ // all right
+ //
+ if (!VerifyArgumentsCompat (ec, Arguments, arg_count, best_candidate,
+ method_params, null, may_fail, loc))
+ return null;
+
+ if (best_candidate == null)
+ return null;
+
+ MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
+#if GMCS_SOURCE
+ if (the_method.IsGenericMethodDefinition &&
+ !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
+ return null;
+#endif
+
+ IMethodData data = TypeManager.GetMethod (the_method);
+ if (data != null)
+ data.SetMemberIsUsed ();
+
+ return this;
+ }
+
public Expression ResolveGeneric (EmitContext ec, TypeArguments args)
{
#if GMCS_SOURCE
- if (args.Resolve (ec) == false)
+ if (!args.Resolve (ec))
return null;
Type[] atypes = args.Arguments;
ArrayList list = new ArrayList ();
foreach (MethodBase mb in Methods) {
MethodInfo mi = mb as MethodInfo;
- if ((mi == null) || !mi.IsGenericMethod)
+ if ((mi == null) || !mb.IsGenericMethod)
continue;
- Type[] gen_params = mi.GetGenericArguments ();
+ Type[] gen_params = mb.GetGenericArguments ();
if (first == null) {
first = mi;
if (gen_params.Length != atypes.Length)
continue;
- list.Add (mi.MakeGenericMethod (atypes));
+ mi = mi.MakeGenericMethod (atypes);
+ list.Add (mi);
+
+#if MS_COMPATIBLE
+ // MS implementation throws NotSupportedException for GetParameters
+ // on unbaked generic method
+ Parameters p = TypeManager.GetParameterData (mi) as Parameters;
+ if (p != null) {
+ p = p.Clone ();
+ p.InflateTypes (gen_params, atypes);
+ TypeManager.RegisterMethod (mi, p);
+ }
+#endif
}
if (list.Count > 0) {
- MethodGroupExpr new_mg = new MethodGroupExpr (list, Location);
- new_mg.InstanceExpression = InstanceExpression;
- new_mg.HasTypeArguments = true;
- new_mg.IsBase = IsBase;
- return new_mg;
+ this.Methods = (MethodBase []) list.ToArray (typeof (MethodBase));
+ has_type_arguments = true;
+ return this;
}
- if (first != null)
+ if (first != null) {
+ Report.SymbolRelatedToPreviousError (first);
Report.Error (
- 305, loc, "Using the generic method `{0}' " +
- "requires {1} type arguments", Name,
- first_count.ToString ());
- else
+ 305, loc, "Using the generic method `{0}' requires `{1}' type arguments",
+ TypeManager.CSharpSignature (first), first_count.ToString ());
+ } else
Report.Error (
308, loc, "The non-generic method `{0}' " +
"cannot be used with type arguments", Name);
throw new NotImplementedException ();
#endif
}
+
+ public bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
+ int arg_count, MethodBase method,
+ bool chose_params_expanded,
+ Type delegate_type, bool may_fail, Location loc)
+ {
+ ParameterData pd = TypeManager.GetParameterData (method);
+ int param_count = GetApplicableParametersCount (method, pd);
+
+ int j;
+ int a_idx = 0;
+ Argument a = null;
+ int errors = Report.Errors;
+ for (j = 0; j < param_count; j++) {
+ Type parameter_type = pd.ParameterType (j);
+ Parameter.Modifier pm = pd.ParameterModifier (j);
+
+ if (pm == Parameter.Modifier.ARGLIST) {
+ a = (Argument) Arguments [a_idx];
+ if (!(a.Expr is Arglist))
+ break;
+ ++a_idx;
+ continue;
+ }
+
+ int params_arg_count = 1;
+ if (pm == Parameter.Modifier.PARAMS) {
+ pm = Parameter.Modifier.NONE;
+ params_arg_count = arg_count - param_count + 1;
+ if (chose_params_expanded)
+ parameter_type = TypeManager.GetElementType (parameter_type);
+ }
+
+ while (params_arg_count > 0) {
+ a = (Argument) Arguments [a_idx];
+ if (pm != a.Modifier)
+ break;
+
+ if (!TypeManager.IsEqual (a.Type, parameter_type)) {
+ if (pm == Parameter.Modifier.OUT || pm == Parameter.Modifier.REF)
+ break;
+
+ Expression conv = Convert.ImplicitConversion (ec, a.Expr, parameter_type, loc);
+ if (conv == null)
+ break;
+
+ // Update the argument with the implicit conversion
+ if (a.Expr != conv)
+ a.Expr = conv;
+ }
+
+ --params_arg_count;
+ ++a_idx;
+ }
+ if (params_arg_count > 0)
+ break;
+
+ if (parameter_type.IsPointer && !ec.InUnsafe) {
+ if (!may_fail)
+ UnsafeError (loc);
+ return false;
+ }
+ }
+
+ if (a_idx == arg_count)
+ return true;
+
+ if (!may_fail && Report.Errors == errors)
+ Error_InvalidArguments (ec, loc, a_idx, method, delegate_type, a, pd);
+ return false;
+ }
}
/// <summary>
if (t.IsPointer && !ec.InUnsafe) {
UnsafeError (loc);
- return null;
}
return base.ResolveMemberAccess (ec, left, loc, original);
InstanceExpression.CheckMarshalByRefAccess ();
}
- if (!in_initializer && !ec.IsFieldInitializer) {
+ if (!in_initializer && !ec.IsInFieldInitializer) {
ObsoleteAttribute oa;
FieldBase f = TypeManager.GetField (FieldInfo);
if (f != null) {
}
}
}
-
+
+ IFixedBuffer fb = AttributeTester.GetFixedBuffer (FieldInfo);
+ if (fb != null) {
+ if (!ec.InFixedInitializer && ec.ContainerType.IsValueType) {
+ Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement");
+ }
+
+ if (!(InstanceExpression is LocalVariableReference) &&
+ !(InstanceExpression is This)) {
+ Report.SymbolRelatedToPreviousError (FieldInfo);
+ Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields",
+ TypeManager.GetFullNameSignature (FieldInfo));
+ }
+
+ return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec);
+ }
+
// If the instance expression is a local variable or parameter.
IVariable var = InstanceExpression as IVariable;
if ((var == null) || (var.VariableInfo == null))
if (FieldInfo.IsInitOnly) {
// InitOnly fields can only be assigned in constructors or initializers
- if (!ec.IsFieldInitializer && !ec.IsConstructor)
+ if (!ec.IsInFieldInitializer && !ec.IsConstructor)
return Report_AssignToReadonly (right_side);
if (ec.IsConstructor) {
if (!prepared)
EmitInstance (ec, false);
- if (is_volatile)
- ig.Emit (OpCodes.Volatile);
-
IFixedBuffer ff = AttributeTester.GetFixedBuffer (FieldInfo);
- if (ff != null)
- {
+ if (ff != null) {
ig.Emit (OpCodes.Ldflda, FieldInfo);
ig.Emit (OpCodes.Ldflda, ff.Element);
- }
- else {
+ } else {
+ if (is_volatile)
+ ig.Emit (OpCodes.Volatile);
+
ig.Emit (OpCodes.Ldfld, FieldInfo);
}
}
bool is_static = (fa & FieldAttributes.Static) != 0;
bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
ILGenerator ig = ec.ig;
- prepared = prepare_for_load;
if (is_readonly && !ec.IsConstructor){
Report_AssignToReadonly (source);
return;
}
- EmitInstance (ec, prepare_for_load);
+ //
+ // String concatenation creates a new string instance
+ //
+ prepared = prepare_for_load && !(source is StringConcat);
+ EmitInstance (ec, prepared);
- source.Emit (ec);
+ source.Emit (ec);
if (leave_copy) {
ec.ig.Emit (OpCodes.Dup);
if (!FieldInfo.IsStatic) {
FieldBase f = TypeManager.GetField (FieldInfo);
if (f != null){
if ((f.ModFlags & Modifiers.VOLATILE) != 0){
- Report.Warning (420, 1, loc, "`{0}': A volatile fields cannot be passed using a ref or out parameter",
+ Report.Warning (420, 1, loc, "`{0}': A volatile field references will not be treated as volatile",
f.GetSignatureForError ());
- return;
}
if ((mode & AddressOp.Store) != 0)
Report.Error (1546, loc, "Property `{0}' is not supported by the C# language. Try to call the accessor method `{1}' directly",
Name, sig.ToString ());
}
-
+
+ public bool IsAccessibleFrom (Type invocation_type, bool lvalue)
+ {
+ bool dummy;
+ MethodInfo accessor = lvalue ? setter : getter;
+ if (accessor == null && lvalue)
+ accessor = getter;
+ return accessor != null && IsAccessorAccessible (invocation_type, accessor, out dummy);
+ }
+
override public Expression DoResolve (EmitContext ec)
{
if (resolved)
override public 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",
+ if (ec.CurrentBlock.Toplevel.GetTransparentIdentifier (PropertyInfo.Name) != null) {
+ Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter",
+ PropertyInfo.Name);
+ } else {
+ Report.Error (206, loc, "A property or indexer `{0}' may not be passed as `ref' or `out' parameter",
GetSignatureForError ());
+ }
return null;
}
}
}
- Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, getter, null, loc, prepared, false);
+ Invocation.EmitCall (ec, IsBase, InstanceExpression, getter, null, loc, prepared, false);
if (leave_copy) {
ec.ig.Emit (OpCodes.Dup);
{
Expression my_source = source;
- prepared = prepare_for_load;
-
- if (prepared) {
+ if (prepare_for_load) {
+ if (source is StringConcat)
+ EmitInstance (ec, false);
+ else
+ prepared = true;
+
source.Emit (ec);
+
+ prepared = true;
if (leave_copy) {
ec.ig.Emit (OpCodes.Dup);
if (!is_static) {
}
} else if (leave_copy) {
source.Emit (ec);
- if (!is_static) {
- temp = new LocalTemporary (this.Type);
- temp.Store (ec);
- }
+ temp = new LocalTemporary (this.Type);
+ temp.Store (ec);
my_source = temp;
}
-
+
ArrayList args = new ArrayList (1);
args.Add (new Argument (my_source, Argument.AType.Expression));
- Invocation.EmitCall (ec, IsBase, IsStatic, InstanceExpression, setter, args, loc, false, prepared);
+ Invocation.EmitCall (ec, IsBase, InstanceExpression, setter, args, loc, false, prepared);
if (temp != null) {
temp.Emit (ec);
/// </summary>
public class EventExpr : MemberExpr {
public readonly EventInfo EventInfo;
+ public bool IsBase;
bool is_static;
MethodInfo add_accessor, remove_accessor;
if (InstanceExpression == null)
return false;
+ if (IsBase && add_accessor.IsAbstract) {
+ Error_CannotCallAbstractBase(TypeManager.CSharpSignature(add_accessor));
+ return false;
+ }
+
//
// This is using the same mechanism as the CS1540 check in PropertyExpr.
// However, in the Event case, we reported a CS0122 instead.
return true;
}
+ public bool IsAccessibleFrom (Type invocation_type)
+ {
+ bool dummy;
+ return IsAccessorAccessible (invocation_type, add_accessor, out dummy) &&
+ IsAccessorAccessible (invocation_type, remove_accessor, out dummy);
+ }
+
public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
{
return DoResolve (ec);
if (source_del.IsAddition)
Invocation.EmitCall (
- ec, false, IsStatic, InstanceExpression, add_accessor, args, loc);
+ ec, IsBase, InstanceExpression, add_accessor, args, loc);
else
Invocation.EmitCall (
- ec, false, IsStatic, InstanceExpression, remove_accessor, args, loc);
+ ec, IsBase, InstanceExpression, remove_accessor, args, loc);
}
}
EmitLoadAddress (ec);
}
}
-
+
+ ///
+ /// Handles `var' contextual keyword; var becomes a keyword only
+ /// if no type called var exists in a variable scope
+ ///
+ public class VarExpr : SimpleName
+ {
+ // Used for error reporting only
+ ArrayList initializer;
+
+ public VarExpr (string name, Location loc)
+ : base (name, loc)
+ {
+ }
+
+ public ArrayList VariableInitializer {
+ set {
+ this.initializer = value;
+ }
+ }
+
+ public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
+ {
+ if (type != null)
+ throw new InternalErrorException ("An implicitly typed local variable could not be redefined");
+
+ type = right_side.Type;
+ if (type == TypeManager.null_type || type == TypeManager.void_type || type == TypeManager.anonymous_method_type) {
+ Report.Error (815, loc, "An implicitly typed local variable declaration cannot be initialized with `{0}'",
+ right_side.GetSignatureForError ());
+ return null;
+ }
+
+ eclass = ExprClass.Variable;
+ return this;
+ }
+
+ protected override void Error_TypeOrNamespaceNotFound (IResolveContext ec)
+ {
+ if (ec is FieldBase) {
+ Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration");
+ return;
+ }
+
+ base.Error_TypeOrNamespaceNotFound (ec);
+ }
+
+ public override TypeExpr ResolveAsContextualType (IResolveContext rc, bool silent)
+ {
+ TypeExpr te = base.ResolveAsContextualType (rc, true);
+ if (te != null)
+ return te;
+
+ if (initializer == null)
+ return null;
+
+ // TODO: refactor, the error is reported too many times
+ if (initializer.Count > 1) {
+ Location loc = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [1]).Location;
+ Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators");
+ return null;
+ }
+
+ Expression variable_initializer = ((Mono.CSharp.CSharpParser.VariableDeclaration)initializer [0]).expression_or_array_initializer;
+ if (variable_initializer == null) {
+ Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer");
+ return null;
+ }
+
+ return null;
+ }
+ }
}