namespace Mono.CSharp {
+ public enum SpecialConstraint
+ {
+ Constructor,
+ ReferenceType,
+ ValueType
+ }
+
//
// Tracks the constraints for a type parameter
//
- public class Constraints {
- string type_parameter;
+ public class Constraints : GenericConstraints {
+ string name;
ArrayList constraints;
Location loc;
//
- // type_parameter is the identifier, constraints is an arraylist of
+ // name is the identifier, constraints is an arraylist of
// Expressions (with types) or `true' for the constructor constraint.
//
- public Constraints (string type_parameter, ArrayList constraints,
+ public Constraints (string name, ArrayList constraints,
Location loc)
{
- this.type_parameter = type_parameter;
+ this.name = name;
this.constraints = constraints;
this.loc = loc;
}
public string TypeParameter {
get {
- return type_parameter;
+ return name;
}
}
- protected void Error (string message)
- {
- Report.Error (-218, "Invalid constraints clause for type " +
- "parameter `{0}': {1}", type_parameter, message);
- }
-
bool has_ctor_constraint;
+ bool has_reference_type;
+ bool has_value_type;
TypeExpr class_constraint;
ArrayList iface_constraints;
- TypeExpr[] constraint_types;
- int num_constraints;
+ ArrayList type_param_constraints;
+ int num_constraints, first_constraint;
+ Type class_constraint_type;
+ Type[] iface_constraint_types;
public bool HasConstructorConstraint {
get { return has_ctor_constraint; }
public bool Resolve (DeclSpace ds)
{
iface_constraints = new ArrayList ();
+ type_param_constraints = new ArrayList ();
foreach (object obj in constraints) {
if (has_ctor_constraint) {
- Error ("can only use one constructor constraint and " +
- "it must be the last constraint in the list.");
+ Report.Error (401, loc,
+ "The new() constraint must be last.");
return false;
}
- if (obj is bool) {
- has_ctor_constraint = true;
+ if (obj is SpecialConstraint) {
+ SpecialConstraint sc = (SpecialConstraint) obj;
+
+ if (sc == SpecialConstraint.Constructor) {
+ if (!has_value_type) {
+ has_ctor_constraint = true;
+ continue;
+ }
+
+ Report.Error (
+ 451, loc, "The new () constraint " +
+ "cannot be used with the `struct' " +
+ "constraint.");
+ return false;
+ }
+
+ if ((num_constraints > 0) || has_reference_type ||
+ has_value_type) {
+ Report.Error (449, loc,
+ "The `class' or `struct' " +
+ "constraint must be first");
+ return false;
+ }
+
+ if (sc == SpecialConstraint.ReferenceType)
+ has_reference_type = true;
+ else
+ has_value_type = true;
continue;
}
if (expr == null)
return false;
- if (expr.IsInterface)
+ TypeParameterExpr texpr = expr as TypeParameterExpr;
+ if (texpr != null)
+ type_param_constraints.Add (expr);
+ else if (expr.IsInterface)
iface_constraints.Add (expr);
else if (class_constraint != null) {
- Error ("can have at most one class constraint.");
+ Report.Error (406, loc,
+ "`{0}': the class constraint for `{1}' " +
+ "must come before any other constraints.",
+ expr.Name, name);
+ return false;
+ } else if (has_reference_type || has_value_type) {
+ Report.Error (450, loc, "`{0}': cannot specify both " +
+ "a constraint class and the `class' " +
+ "or `struct' constraint.", expr.Name);
return false;
} else
class_constraint = expr;
num_constraints++;
}
- constraint_types = new TypeExpr [num_constraints];
- int pos = 0;
- if (class_constraint != null)
- constraint_types [pos++] = class_constraint;
- iface_constraints.CopyTo (constraint_types, pos);
+ return true;
+ }
+
+ bool CheckTypeParameterConstraints (TypeParameter tparam, Hashtable seen)
+ {
+ seen.Add (tparam, true);
+
+ Constraints constraints = tparam.Constraints;
+ if (constraints == null)
+ return true;
+
+ if (constraints.IsValueType) {
+ Report.Error (456, loc, "Type parameter `{0}' has " +
+ "the `struct' constraint, so it cannot " +
+ "be used as a constraint for `{1}'",
+ tparam.Name, name);
+ return false;
+ }
+
+ if (constraints.type_param_constraints == null)
+ return true;
+
+ foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
+ if (seen.Contains (expr.TypeParameter)) {
+ Report.Error (454, loc, "Circular constraint " +
+ "dependency involving `{0}' and `{1}'",
+ tparam.Name, expr.Name);
+ return false;
+ }
+
+ if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool ResolveTypes (EmitContext ec)
+ {
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ Hashtable seen = new Hashtable ();
+ if (!CheckTypeParameterConstraints (expr.TypeParameter, seen))
+ return false;
+ }
+
+ ArrayList list = new ArrayList ();
+
+ foreach (TypeExpr iface_constraint in iface_constraints) {
+ Type resolved = iface_constraint.ResolveType (ec);
+ if (resolved == null)
+ return false;
+
+ foreach (TypeExpr texpr in list) {
+ if (!texpr.Equals (resolved))
+ continue;
+
+ Report.Error (405, loc,
+ "Duplicate constraint `{0}' for type " +
+ "parameter `{1}'.", resolved, name);
+ return false;
+ }
+
+ list.Add (resolved);
+ }
+
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ Type resolved = expr.ResolveType (ec);
+ if (resolved == null)
+ return false;
+
+ foreach (TypeExpr texpr in list) {
+ if (!texpr.Equals (resolved))
+ continue;
+
+ Report.Error (405, loc,
+ "Duplicate constraint `{0}' for type " +
+ "parameter `{1}'.", resolved, name);
+ return false;
+ }
+
+ list.Add (resolved);
+ }
+
+ iface_constraint_types = new Type [list.Count];
+ list.CopyTo (iface_constraint_types, 0);
+
+ if (class_constraint != null) {
+ class_constraint_type = class_constraint.ResolveType (ec);
+ if (class_constraint_type == null)
+ return false;
+
+ if (class_constraint_type.IsSealed) {
+ Report.Error (701, loc,
+ "`{0}' is not a valid bound. Bounds " +
+ "must be interfaces or non sealed " +
+ "classes", class_constraint_type);
+ return false;
+ }
+
+ if ((class_constraint_type == TypeManager.array_type) ||
+ (class_constraint_type == TypeManager.delegate_type) ||
+ (class_constraint_type == TypeManager.enum_type) ||
+ (class_constraint_type == TypeManager.value_type) ||
+ (class_constraint_type == TypeManager.object_type)) {
+ Report.Error (702, loc,
+ "Bound cannot be special class `{0}'",
+ class_constraint_type);
+ return false;
+ }
+ }
+
+ if (has_reference_type)
+ class_constraint_type = TypeManager.object_type;
+ else if (has_value_type)
+ class_constraint_type = TypeManager.value_type;
+
+ return true;
+ }
+
+ public bool CheckDependencies (EmitContext ec)
+ {
+ foreach (TypeParameterExpr expr in type_param_constraints) {
+ if (!CheckDependencies (expr.TypeParameter, ec))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool CheckDependencies (TypeParameter tparam, EmitContext ec)
+ {
+ Constraints constraints = tparam.Constraints;
+ if (constraints == null)
+ return true;
+
+ if (IsValueType && constraints.HasClassConstraint) {
+ Report.Error (455, loc, "Type parameter `{0}' inherits " +
+ "conflicting constraints `{1}' and `{2}'",
+ name, constraints.ClassConstraint,
+ "System.ValueType");
+ return false;
+ }
+
+ if (HasClassConstraint && constraints.HasClassConstraint) {
+ Type t1 = ClassConstraint;
+ TypeExpr e1 = class_constraint;
+ Type t2 = constraints.ClassConstraint;
+ TypeExpr e2 = constraints.class_constraint;
+
+ if (!Convert.ImplicitReferenceConversionExists (e1, t2) &&
+ !Convert.ImplicitReferenceConversionExists (e2, t1)) {
+ Report.Error (455, loc,
+ "Type parameter `{0}' inherits " +
+ "conflicting constraints `{1}' and `{2}'",
+ name, t1, t2);
+ return false;
+ }
+ }
+
+ if (constraints.type_param_constraints == null)
+ return true;
+
+ foreach (TypeParameterExpr expr in constraints.type_param_constraints) {
+ if (!CheckDependencies (expr.TypeParameter, ec))
+ return false;
+ }
return true;
}
- public Type[] ResolveTypes (EmitContext ec)
+ public void Define (GenericTypeParameterBuilder type)
{
- Type [] types = new Type [constraint_types.Length];
+ if (has_ctor_constraint)
+ type.Mono_SetConstructorConstraint ();
+ if (has_reference_type)
+ type.Mono_SetReferenceTypeConstraint ();
+ else if (has_value_type)
+ type.Mono_SetValueTypeConstraint ();
+ }
- for (int i = 0; i < constraint_types.Length; i++)
- types [i] = constraint_types [i].ResolveType (ec);
+ bool GenericConstraints.HasConstructor {
+ get { return has_ctor_constraint; }
+ }
- return types;
+ bool GenericConstraints.IsReferenceType {
+ get { return has_reference_type; }
+ }
+
+ public bool IsValueType {
+ get { return has_value_type; }
+ }
+
+ public bool HasClassConstraint {
+ get { return class_constraint_type != null; }
+ }
+
+ public Type ClassConstraint {
+ get { return class_constraint_type; }
+ }
+
+ Type[] GenericConstraints.InterfaceConstraints {
+ get { return iface_constraint_types; }
}
}
//
// This type represents a generic type parameter
//
- public class TypeParameter {
+ public class TypeParameter : IMemberContainer {
string name;
Constraints constraints;
Location loc;
- Type type;
+ GenericTypeParameterBuilder type;
public TypeParameter (string name, Constraints constraints, Location loc)
{
}
}
+ public bool HasConstructorConstraint {
+ get {
+ if (constraints != null)
+ return constraints.HasConstructorConstraint;
+
+ return false;
+ }
+ }
+
public Type Type {
get {
return type;
return true;
}
- public Type Define (TypeBuilder tb)
+ public void Define (GenericTypeParameterBuilder type)
{
- type = tb.DefineGenericParameter (name);
- return type;
+ this.type = type;
+ Type[] ifaces = null;
+ if (constraints != null)
+ constraints.Define (type);
+ TypeManager.AddTypeParameter (type, this);
}
- public Type DefineMethod (MethodBuilder mb)
+ public bool DefineType (EmitContext ec)
{
- type = mb.DefineGenericParameter (name);
- return type;
+ if (constraints != null) {
+ if (!constraints.ResolveTypes (ec))
+ return false;
+
+ GenericConstraints gc = (GenericConstraints) constraints;
+
+ if (gc.HasClassConstraint)
+ type.SetBaseTypeConstraint (gc.ClassConstraint);
+
+ type.SetInterfaceConstraints (gc.InterfaceConstraints);
+ TypeManager.RegisterBuilder (type, gc.InterfaceConstraints);
+ }
+
+ return true;
}
- public void DefineType (EmitContext ec, TypeBuilder tb)
+ public bool CheckDependencies (EmitContext ec)
{
- int index = type.GenericParameterPosition;
- if (constraints == null)
- tb.SetGenericParameterConstraints (index, new Type [0]);
- else
- tb.SetGenericParameterConstraints (index, constraints.ResolveTypes (ec));
+ if (constraints != null)
+ return constraints.CheckDependencies (ec);
+
+ return true;
+ }
+
+ //
+ // IMemberContainer
+ //
+
+ IMemberContainer IMemberContainer.ParentContainer {
+ get { return null; }
}
- public void DefineType (EmitContext ec, MethodBuilder mb)
+ bool IMemberContainer.IsInterface {
+ get { return true; }
+ }
+
+ MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ return FindMembers (mt, bf, null, null);
+ }
+
+ MemberCache IMemberContainer.MemberCache {
+ get { return null; }
+ }
+
+ public MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
- int index = type.GenericParameterPosition;
if (constraints == null)
- mb.SetGenericParameterConstraints (index, new Type [0]);
- else
- mb.SetGenericParameterConstraints (index, constraints.ResolveTypes (ec));
+ return MemberList.Empty;
+
+ ArrayList members = new ArrayList ();
+
+ GenericConstraints gc = (GenericConstraints) constraints;
+
+ if (gc.HasClassConstraint) {
+ MemberList list = TypeManager.FindMembers (
+ gc.ClassConstraint, mt, bf, filter, criteria);
+
+ members.AddRange (list);
+ }
+
+ foreach (Type t in gc.InterfaceConstraints) {
+ MemberList list = TypeManager.FindMembers (
+ t, mt, bf, filter, criteria);
+
+ members.AddRange (list);
+ }
+
+ return new MemberList (members);
}
public override string ToString ()
return this;
}
+ public override bool IsInterface {
+ get { return false; }
+ }
+
public void Error_CannotUseAsUnmanagedType (Location loc)
{
Report.Error (-203, loc, "Can not use type parameter as unamanged type");
public readonly Location Location;
ArrayList args;
Type[] atypes;
+ int dimension;
bool has_type_args;
bool created;
this.Location = loc;
}
+ public TypeArguments (int dimension, Location loc)
+ {
+ this.dimension = dimension;
+ this.Location = loc;
+ }
+
public void Add (Expression type)
{
if (created)
public int Count {
get {
- return args.Count;
+ if (dimension > 0)
+ return dimension;
+ else
+ return args.Count;
+ }
+ }
+
+ public bool IsUnbound {
+ get {
+ return dimension > 0;
}
}
{
StringBuilder s = new StringBuilder ();
- int count = args.Count;
+ int count = Count;
for (int i = 0; i < count; i++){
//
// FIXME: Use TypeManager.CSharpname once we have the type
//
- s.Append (args [i].ToString ());
+ if (args != null)
+ s.Append (args [i].ToString ());
if (i+1 < count)
s.Append (",");
}
bool ok = true;
atypes = new Type [count];
-
+
for (int i = 0; i < count; i++){
TypeExpr te = ds.ResolveTypeExpr (
(Expression) args [i], false, Location);
public ConstructedType (string name, TypeArguments args, Location l)
{
loc = l;
- this.name = name;
+ this.name = MemberName.MakeName (name, args.Count);
this.args = args;
eclass = ExprClass.Type;
get { return args; }
}
- protected bool CheckConstraints (int index)
+ protected string DeclarationName {
+ get {
+ StringBuilder sb = new StringBuilder ();
+ sb.Append (gt.FullName);
+ sb.Append ("<");
+ for (int i = 0; i < gen_params.Length; i++) {
+ if (i > 0)
+ sb.Append (",");
+ sb.Append (gen_params [i]);
+ }
+ sb.Append (">");
+ return sb.ToString ();
+ }
+ }
+
+ protected bool CheckConstraint (EmitContext ec, Type ptype, Expression expr,
+ Type ctype)
+ {
+ if (TypeManager.HasGenericArguments (ctype)) {
+ Type[] types = TypeManager.GetTypeArguments (ctype);
+
+ TypeArguments new_args = new TypeArguments (loc);
+
+ for (int i = 0; i < types.Length; i++) {
+ Type t = types [i];
+
+ if (t.IsGenericParameter) {
+ int pos = t.GenericParameterPosition;
+ t = args.Arguments [pos];
+ }
+ new_args.Add (new TypeExpression (t, loc));
+ }
+
+ ctype = new ConstructedType (ctype, new_args, loc).ResolveType (ec);
+ if (ctype == null)
+ return false;
+ }
+
+ return Convert.ImplicitStandardConversionExists (expr, ctype);
+ }
+
+ protected bool CheckConstraints (EmitContext ec, int index)
{
Type atype = atypes [index];
Type ptype = gen_params [index];
- //// FIXME
- return true;
+ if (atype == ptype)
+ return true;
+
+ Expression aexpr = new EmptyExpression (atype);
+
+ Type parent = ptype.BaseType;
//
- // First, check parent class.
+ // First, check the `class' and `struct' constraints.
//
- if ((ptype.BaseType != atype.BaseType) &&
- !atype.BaseType.IsSubclassOf (ptype.BaseType)) {
- Report.Error (-219, loc, "Cannot create constructed type `{0}': " +
- "type argument `{1}' must derive from `{2}'.",
- full_name, atype, ptype.BaseType);
- return false;
+ if (parent == TypeManager.object_type) {
+ if (!atype.IsClass) {
+ Report.Error (452, loc, "The type `{0}' must be " +
+ "a reference type in order to use it " +
+ "as type parameter `{1}' in the " +
+ "generic type or method `{2}'.",
+ atype, ptype, DeclarationName);
+ return false;
+ }
+ } else if (parent == TypeManager.value_type) {
+ if (!atype.IsValueType) {
+ Report.Error (453, loc, "The type `{0}' must be " +
+ "a value type in order to use it " +
+ "as type parameter `{1}' in the " +
+ "generic type or method `{2}'.",
+ atype, ptype, DeclarationName);
+ return false;
+ }
}
//
- // Now, check the interfaces.
+ // The class constraint comes next.
//
- foreach (Type itype in ptype.GetInterfaces ()) {
- if (TypeManager.ImplementsInterface (atype, itype))
- continue;
+ if ((parent != null) && (parent != TypeManager.object_type)) {
+ if (!CheckConstraint (ec, ptype, aexpr, parent)) {
+ Report.Error (309, loc, "The type `{0}' must be " +
+ "convertible to `{1}' in order to " +
+ "use it as parameter `{2}' in the " +
+ "generic type or method `{3}'",
+ atype, parent, ptype, DeclarationName);
+ return false;
+ }
+ }
+
+ //
+ // Now, check the interface constraints.
+ //
+ foreach (Type it in TypeManager.GetInterfaces (ptype)) {
+ Type itype;
+ if (it.IsGenericParameter)
+ itype = atypes [it.GenericParameterPosition];
+ else
+ itype = it;
+
+ if (!CheckConstraint (ec, ptype, aexpr, itype)) {
+ Report.Error (309, loc, "The type `{0}' must be " +
+ "convertible to `{1}' in order to " +
+ "use it as parameter `{2}' in the " +
+ "generic type or method `{3}'",
+ atype, itype, ptype, DeclarationName);
+ return false;
+ }
+ }
+
+ //
+ // Finally, check the constructor constraint.
+ //
+
+ if (!TypeManager.HasConstructorConstraint (ptype))
+ return true;
- Report.Error (-219, loc, "Cannot create constructed type `{0}: " +
- "type argument `{1}' must implement interface `{2}'.",
- full_name, atype, itype);
+ MethodGroupExpr mg = Expression.MemberLookup (
+ ec, atype, ".ctor", MemberTypes.Constructor,
+ BindingFlags.Public | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly, loc)
+ as MethodGroupExpr;
+
+ if (atype.IsAbstract || (mg == null) || !mg.IsInstance) {
+ Report.Error (310, loc, "The type `{0}' must have a public " +
+ "parameterless constructor in order to use it " +
+ "as parameter `{1}' in the generic type or " +
+ "method `{2}'", atype, ptype, DeclarationName);
return false;
}
return this;
}
- SimpleName sn = new SimpleName (name, args.Count, loc);
- TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
- if (resolved == null) {
- sn = new SimpleName (name, -1, loc);
- resolved = sn.ResolveAsTypeTerminal (ec);
- if ((resolved == null) || (resolved.Type == null)) {
- Report.Error (246, loc,
- "The type or namespace name `{0}<...>' "+
- "could not be found", name);
- return null;
- }
+ Type t;
+ int num_args;
- Type t = resolved.Type;
- int num_args = TypeManager.GetNumberOfTypeArguments (t);
-
- if (num_args == 0) {
- Report.Error (308, loc,
- "The non-generic type `{0}' cannot " +
- "be used with type arguments.",
- TypeManager.CSharpName (t));
- return null;
- }
+ SimpleName sn = new SimpleName (name, loc);
+ TypeExpr resolved = sn.ResolveAsTypeTerminal (ec);
+ if ((resolved == null) || (resolved.Type == null)) {
+ Report.Error (246, loc,
+ "The type or namespace name `{0}<...>' "+
+ "could not be found", Basename);
+ return null;
+ }
- Report.Error (305, loc,
- "Using the generic type `{0}' " +
- "requires {1} type arguments",
- TypeManager.GetFullName (t), num_args);
+ t = resolved.Type;
+ if (t == null) {
+ Report.Error (246, loc, "Cannot find type `{0}'<...>",
+ Basename);
return null;
}
- if (resolved.Type == null)
- throw new InternalErrorException (
- "Failed to resolve constructed type `{0}'",
- full_name);
+ num_args = TypeManager.GetNumberOfTypeArguments (t);
+ if (num_args == 0) {
+ Report.Error (308, loc,
+ "The non-generic type `{0}' cannot " +
+ "be used with type arguments.",
+ TypeManager.CSharpName (t));
+ return null;
+ }
- gt = resolved.Type.GetGenericTypeDefinition ();
+ gt = t.GetGenericTypeDefinition ();
return this;
}
atypes = args.Arguments;
if (atypes.Length != gen_params.Length) {
- Report.Error (-217, loc, "Generic type `{0}' takes {1} " +
- "type parameters, but specified {2}.", gt.Name,
- gen_params.Length, atypes.Length);
+ Report.Error (305, loc,
+ "Using the generic type `{0}' " +
+ "requires {1} type arguments",
+ TypeManager.GetFullName (gt),
+ gen_params.Length);
return null;
}
for (int i = 0; i < gen_params.Length; i++) {
- if (!CheckConstraints (i))
+ if (!CheckConstraints (ec, i))
return null;
}
return type;
}
- public Expression GetMemberAccess (EmitContext ec)
+ public Expression GetSimpleName (EmitContext ec)
{
- TypeExpr current;
- if (ec.TypeContainer.CurrentType != null)
- current = ec.TypeContainer.CurrentType;
- else
- current = new TypeExpression (ec.ContainerType, loc);
-
- return new GenericMemberAccess (current, name, args, loc);
+ return new SimpleName (Basename, args, loc);
}
public override bool CheckAccessLevel (DeclSpace ds)
get { return false; }
}
- public override TypeExpr[] GetInterfaces ()
- {
- TypeExpr[] ifaces = TypeManager.GetInterfaces (gt);
- return ifaces;
- }
-
public override bool Equals (object obj)
{
ConstructedType cobj = obj as ConstructedType;
return type == cobj.type;
}
+ public string Basename {
+ get {
+ int pos = name.LastIndexOf ('`');
+ if (pos >= 0)
+ return name.Substring (0, pos);
+ else
+ return name;
+ }
+ }
+
public override string Name {
get {
return full_name;
public class GenericMethod : DeclSpace
{
- public GenericMethod (NamespaceEntry ns, TypeContainer parent, string name,
- Attributes attrs, Location l)
- : base (ns, parent, name, attrs, l)
+ public GenericMethod (NamespaceEntry ns, TypeContainer parent,
+ MemberName name, Location l)
+ : base (ns, parent, name, null, l)
{ }
public override TypeBuilder DefineType ()
throw new Exception ();
}
- public override bool Define (TypeContainer parent)
+ public override bool Define ()
{
+ for (int i = 0; i < TypeParameters.Length; i++)
+ if (!TypeParameters [i].Resolve (Parent))
+ return false;
+
return true;
}
public bool Define (MethodBuilder mb)
{
- Type[] gen_params = new Type [TypeParameters.Length];
+ if (!Define ())
+ return false;
+
+ GenericTypeParameterBuilder[] gen_params;
+ string[] names = MemberName.TypeArguments.GetDeclarations ();
+ gen_params = mb.DefineGenericParameters (names);
for (int i = 0; i < TypeParameters.Length; i++)
- gen_params [i] = TypeParameters [i].DefineMethod (mb);
+ TypeParameters [i].Define (gen_params [i]);
return true;
}
public bool DefineType (EmitContext ec, MethodBuilder mb)
{
for (int i = 0; i < TypeParameters.Length; i++)
- TypeParameters [i].DefineType (ec, mb);
+ if (!TypeParameters [i].DefineType (ec))
+ return false;
return true;
}
throw new Exception ();
}
}
- }
- public class GenericMemberAccess : MemberAccess
- {
- TypeArguments args;
-
- public GenericMemberAccess (Expression expr, string id, TypeArguments args, Location loc)
- : base (expr, id, args.Count, loc)
+ public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
{
- this.args = args;
+ // FIXME
}
- private bool DoResolveBase (EmitContext ec)
+ protected override void VerifyObsoleteAttribute()
{
- ConstructedType cexpr = expr as ConstructedType;
- if (cexpr != null) {
- TypeArguments new_args = new TypeArguments (loc);
- new_args.Add (cexpr.TypeArguments);
- new_args.Add (args);
-
- args = new_args;
- }
-
- return true;
+ // FIXME
}
- public override Expression DoResolve (EmitContext ec, Expression right_side,
- ResolveFlags flags)
- {
- if (!DoResolveBase (ec))
- return null;
-
- Expression expr = base.DoResolve (ec, right_side, flags);
- if (expr == null)
- return null;
-
- TypeExpr texpr = expr as TypeExpr;
- if (texpr != null) {
- Type t = texpr.ResolveType (ec);
- if (t == null)
- return null;
-
- ConstructedType ctype = new ConstructedType (t, args, loc);
- return ctype.DoResolve (ec);
- }
-
- MethodGroupExpr mg = expr as MethodGroupExpr;
- if (mg == null) {
- return expr;
- Report.Error (-220, loc, "Member `{0}' has type arguments, but did " +
- "not resolve as a method group.", Identifier);
- return null;
- }
-
- if (args.Resolve (ec) == false)
- return null;
-
- Type[] atypes = args.Arguments;
-
- ArrayList list = new ArrayList ();
-
- foreach (MethodBase method in mg.Methods) {
- MethodInfo mi = method as MethodInfo;
- if (mi == null)
- continue;
-
- Type[] gen_params = mi.GetGenericArguments ();
-
- if (atypes.Length != gen_params.Length) {
- Report.Error (-217, loc, "Generic method `{0}' takes {1} " +
- "type parameters, but specified {2}.", mi.Name,
- gen_params.Length, atypes.Length);
- continue;
- }
-
- list.Add (mi.BindGenericParameters (args.Arguments));
+ public override AttributeTargets AttributeTargets {
+ get {
+ return AttributeTargets.Method | AttributeTargets.ReturnValue;
}
-
- MethodInfo[] methods = new MethodInfo [list.Count];
- list.CopyTo (methods, 0);
-
- MethodGroupExpr new_mg = new MethodGroupExpr (methods, mg.Location);
- new_mg.InstanceExpression = mg.InstanceExpression;
- return new_mg;
- }
-
- public override Expression ResolveAsTypeStep (EmitContext ec)
- {
- if (!DoResolveBase (ec))
- return null;
-
- expr = base.ResolveAsTypeStep (ec);
- if (expr == null)
- return null;
-
- Type t = ((TypeExpr) expr).ResolveType (ec);
- if (t == null)
- return null;
-
- ConstructedType ctype = new ConstructedType (t, args, loc);
- return ctype.ResolveAsTypeStep (ec);
}
}