interfaces.Add (iface);
}
- public void AddField (Field field)
+ public void AddField (FieldMember field)
{
if (!AddToMemberContainer (field))
return;
if (a == null)
return false;
+ if (RootContext.Optimize) {
+ Constant c = e as Constant;
+ if (c != null) {
+ if (c.IsDefaultValue)
+ continue;
+ }
+ }
+
a.EmitStatement (ec);
}
CurrentTypeParameters [i - offset].DefineConstraints ();
current_type = new ConstructedType (Name, TypeParameters, Location);
- }
- if (IsGeneric) {
- foreach (TypeParameter type_param in TypeParameters)
+ foreach (TypeParameter type_param in TypeParameters) {
if (!type_param.DefineType (ec)) {
error = true;
return null;
}
+ }
+
+ if (!CheckConstraints (ec)) {
+ error = true;
+ return null;
+ }
}
if ((Kind == Kind.Struct) && TypeManager.value_type == null)
return TypeBuilder;
}
+ protected virtual bool CheckConstraints (EmitContext ec)
+ {
+ return true;
+ }
+
protected virtual bool DefineNestedTypes ()
{
if (Interfaces != null) {
protected virtual bool DoDefineMembers ()
{
- //
- // We need to be able to use the member cache while we are checking/defining
- //
- if (TypeBuilder.BaseType != null)
- base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
-
- if (TypeBuilder.IsInterface)
- base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
-
if (IsTopLevel) {
if ((ModFlags & Modifiers.NEW) != 0)
Error_KeywordNotAllowed (Location);
DefineContainerMembers (constants);
DefineContainerMembers (fields);
- if ((Kind == Kind.Class) && !(this is ClassPart) && !(this is StaticClass)){
+ if ((Kind == Kind.Class) && !(this is ClassPart)){
if ((instance_constructors == null) &&
!(this is StaticClass)) {
if (default_constructor == null)
if (fields != null) {
int len = fields.Count;
for (int i = 0; i < len; i++) {
- Field f = (Field) fields [i];
+ FieldMember f = (FieldMember) fields [i];
if ((f.ModFlags & modflags) == 0)
continue;
continue;
FieldBuilder fb = con.FieldBuilder;
+ if (fb == null) {
+ if (con.Define ())
+ fb = con.FieldBuilder;
+ }
if (fb != null && filter (fb, criteria) == true) {
if (members == null)
members = new ArrayList ();
continue;
TypeBuilder tb = t.TypeBuilder;
+ if (tb == null)
+ tb = t.DefineType ();
+
if (tb != null && (filter (tb, criteria) == true)) {
if (members == null)
members = new ArrayList ();
}
if (fields != null)
- foreach (Field f in fields)
+ foreach (FieldMember f in fields)
f.Emit ();
if (events != null){
public virtual MemberCache BaseCache {
get {
+ if (base_cache != null)
+ return base_cache;
+ if (TypeBuilder.BaseType != null)
+ base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
+ if (TypeBuilder.IsInterface)
+ base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
return base_cache;
}
}
return null;
}
+ if (pc.IsGeneric) {
+ if (pc.CountTypeParameters != member_name.CountTypeArguments) {
+ Report.Error (
+ 264, loc, "Partial declarations of `{0}' " +
+ "must have the same type parameter names in " +
+ "the same order", member_name.GetTypeName ());
+ return null;
+ }
+
+ string[] pc_names = pc.MemberName.TypeArguments.GetDeclarations ();
+ string[] names = member_name.TypeArguments.GetDeclarations ();
+
+ for (int i = 0; i < pc.CountTypeParameters; i++) {
+ if (pc_names [i] == names [i])
+ continue;
+
+ Report.Error (
+ 264, loc, "Partial declarations of `{0}' " +
+ "must have the same type parameter names in " +
+ "the same order", member_name.GetTypeName ());
+ return null;
+ }
+ }
+
return pc;
}
RootContext.Tree.RecordDecl (full_name, pc);
parent.AddType (pc);
pc.Register ();
+ // This is needed to define our type parameters; we define the constraints later.
+ pc.SetParameterInfo (null);
return pc;
}
return PendingImplementation.GetPendingImplementations (this);
}
+ ArrayList constraints_lists;
+
+ public void UpdateConstraints (ArrayList constraints_list)
+ {
+ //
+ // This is called for each ClassPart in a partial generic type declaration.
+ //
+ // If no constraints were specified for the part, just return.
+ // Otherwise, if we're called with constraints for the first time, they become
+ // the type's constraint. If we're called with constraints again, we just
+ // store them somewhere so we can later check whether there are no conflicts.
+ //
+ if (constraints_list == null)
+ return;
+
+ if (constraints_lists != null) {
+ constraints_lists.Add (constraints_list);
+ return;
+ }
+
+ DoUpdateConstraints (null, constraints_list, false);
+
+ constraints_lists = new ArrayList ();
+ }
+
+ protected bool DoUpdateConstraints (EmitContext ec, ArrayList constraints_list, bool check)
+ {
+ for (int i = 0; i < TypeParameters.Length; i++) {
+ string name = TypeParameters [i].Name;
+
+ Constraints constraints = null;
+ if (constraints_list != null) {
+ foreach (Constraints constraint in constraints_list) {
+ if (constraint.TypeParameter == name) {
+ constraints = constraint;
+ break;
+ }
+ }
+ }
+
+ if (!TypeParameters [i].UpdateConstraints (ec, constraints, check)) {
+ Report.Error (265, Location, "Partial declarations of `{0}' have " +
+ "inconsistent constraints for type parameter `{1}'.",
+ MemberName.GetTypeName (), name);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ protected override bool CheckConstraints (EmitContext ec)
+ {
+ if (constraints_lists == null)
+ return true;
+
+ //
+ // If constraints were specified in more than one part of a
+ // partial generic type definition, they must be identical.
+ //
+ // Note that we must resolve them and then compute the fully
+ // resolved types since different parts may have different
+ // `using' aliases. See gen-129.cs for an example.
+
+ foreach (ArrayList constraints_list in constraints_lists) {
+ if (!DoUpdateConstraints (ec, constraints_list, true))
+ return false;
+ }
+
+ return true;
+ }
+
public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
Location l)
{
interface_type, full, name, loc);
}
+ public override void SetParameterInfo (ArrayList constraints_list)
+ {
+ PartialContainer.UpdateConstraints (constraints_list);
+ }
+
public override MemberCache BaseCache {
get {
return PartialContainer.BaseCache;
protected override bool CheckGenericOverride (MethodInfo method, string name)
{
- ParameterData pd = Invocation.GetParameterData (method);
+ ParameterData pd = TypeManager.GetParameterData (method);
for (int i = 0; i < ParameterTypes.Length; i++) {
GenericConstraints ogc = pd.GenericConstraints (i);
}
if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
- Report.SymbolRelatedToPreviousError (conflict_symbol);
- Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
- }
+ Report.SymbolRelatedToPreviousError (conflict_symbol);
+ Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
+ }
return true;
}
return TypeManager.GetFullNameSignature (FieldBuilder);
}
+ protected virtual bool IsFieldClsCompliant {
+ get {
+ if (FieldBuilder == null)
+ return true;
+
+ return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
+ }
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;
if (!base.VerifyClsCompliance (ds))
return false;
- if (FieldBuilder == null) {
- return true;
- }
-
- if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
+ if (!IsFieldClsCompliant) {
Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
}
return true;
MemberType = texpr.Type;
+ ec.InUnsafe = old_unsafe;
+
if (MemberType == TypeManager.void_type) {
Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
return false;
}
- ec.InUnsafe = old_unsafe;
-
if (!CheckBase ())
return false;
public override void Emit ()
{
+ if (OptAttributes != null) {
+ EmitContext ec = new EmitContext (Parent, Location, null, FieldBuilder.FieldType, ModFlags);
+ OptAttributes.Emit (ec, this);
+ }
+
if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
}
}
}
+ interface IFixedBuffer
+ {
+ FieldInfo Element { get; }
+ Type ElementType { get; }
+ }
+
+ public class FixedFieldExternal: IFixedBuffer
+ {
+ FieldInfo element_field;
+
+ public FixedFieldExternal (FieldInfo fi)
+ {
+ element_field = fi.FieldType.GetField (FixedField.FixedElementName);
+ }
+
+ #region IFixedField Members
+
+ public FieldInfo Element {
+ get {
+ return element_field;
+ }
+ }
+
+ public Type ElementType {
+ get {
+ return element_field.FieldType;
+ }
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Fixed buffer implementation
+ /// </summary>
+ public class FixedField: FieldMember, IFixedBuffer
+ {
+ public const string FixedElementName = "FixedElementField";
+ static int GlobalCounter = 0;
+ static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
+ static FieldInfo[] fi;
+
+ TypeBuilder fixed_buffer_type;
+ FieldBuilder element;
+ Expression size_expr;
+ int buffer_size;
+
+ const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE;
+
+ public FixedField (TypeContainer parent, Expression type, int mod, string name,
+ Expression size_expr, Attributes attrs, Location loc):
+ base (parent, type, mod, AllowedModifiers, new MemberName (name), null, attrs, loc)
+ {
+ if (RootContext.Version == LanguageVersion.ISO_1)
+ Report.FeatureIsNotStandardized (loc, "fixed sized buffers");
+
+ this.size_expr = size_expr;
+ }
+
+ public override bool Define()
+ {
+#if !NET_2_0
+ if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) != 0)
+ Report.Warning (-23, Location, "Only not private or internal fixed sized buffers are supported by .NET 1.x");
+#endif
+
+ if (Parent.Kind != Kind.Struct) {
+ Report.Error (1642, Location, "Fixed buffer fields may only be members of structs");
+ return false;
+ }
+
+ if (!base.Define ())
+ return false;
+
+ if (!MemberType.IsPrimitive) {
+ Report.Error (1663, Location, "Fixed sized buffer type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double");
+ return false;
+ }
+
+ Expression e = size_expr.Resolve (Parent.EmitContext);
+ if (e == null)
+ return false;
+
+ Constant c = e as Constant;
+ if (c == null) {
+ Report.Error (133, Location, "The expression being assigned to '{0}' must be constant", GetSignatureForError ());
+ return false;
+ }
+
+ buffer_size = (int)c.GetValue ();
+ if (buffer_size <= 0) {
+ Report.Error (1665, Location, "Fixed sized buffer '{0}' must have a length greater than zero", GetSignatureForError ());
+ return false;
+ }
+ buffer_size *= Expression.GetTypeSize (MemberType);
+
+ // Define nested
+ string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
+
+ fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
+ TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
+ element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
+ RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
+
+ FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
+ TypeManager.RegisterFieldBase (FieldBuilder, this);
+
+ return true;
+ }
+
+ public override void Emit()
+ {
+ if (fi == null)
+ fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
+
+ object[] fi_val = new object[1];
+ fi_val [0] = buffer_size;
+
+ CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor,
+ ctor_args, fi, fi_val);
+ fixed_buffer_type.SetCustomAttribute (cab);
+
+#if NET_2_0
+ cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
+ FieldBuilder.SetCustomAttribute (cab);
+#endif
+ base.Emit ();
+ }
+
+ protected override bool IsFieldClsCompliant {
+ get {
+ return false;
+ }
+ }
+
+ #region IFixedField Members
+
+ public FieldInfo Element {
+ get {
+ return element;
+ }
+ }
+
+ public Type ElementType {
+ get {
+ return MemberType;
+ }
+ }
+
+ #endregion
+ }
+
//
// The Field class is used to represents class/struct fields during parsing.
//
return true;
}
-
- public override void Emit ()
- {
- if (OptAttributes != null) {
- EmitContext ec = new EmitContext (
- Parent, Location, null, FieldBuilder.FieldType,
- ModFlags);
- OptAttributes.Emit (ec, this);
- }
-
- base.Emit ();
- }
}
//