// rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
//
// Author: Miguel de Icaza (miguel@ximian.com)
+// Ravi Pratap (ravi@ximian.com)
//
// Licensed under the terms of the GNU GPL
//
//
// Contains the parsed tree
//
- Tree tree;
+ static Tree tree;
//
- // Contains loaded assemblies and our generated code as we go.
+ // This hashtable contains all of the #definitions across the source code
+ // it is used by the ConditionalAttribute handler.
//
- public TypeManager TypeManager;
-
- //
- // The System.Reflection.Emit CodeGenerator
- //
- CodeGen cg;
-
- static public bool Optimize;
+ public static Hashtable AllDefines = new Hashtable ();
//
- // The module builder pointer.
+ // The list of global attributes (those that target the assembly)
//
- static ModuleBuilder mb;
-
+ static Hashtable global_attributes = new Hashtable ();
+
//
// Whether we are being linked against the standard libraries.
// This is only used to tell whether `System.Object' should
// have a parent or not.
//
- static bool stdlib = true;
+ public static bool StdLib = true;
//
// This keeps track of the order in which classes were defined
// or abstract as well as the parent names (to implement new,
// override).
//
- ArrayList type_container_resolve_order;
- ArrayList interface_resolve_order;
-
+ static ArrayList type_container_resolve_order;
+ static ArrayList interface_resolve_order;
+ static ArrayList attribute_types;
+
//
// Holds a reference to the Private Implementation Details
// class.
//
- TypeBuilder impl_details_class;
+ static TypeBuilder impl_details_class;
+ public static int WarningLevel = 2;
+
//
// Constructor
//
- public RootContext ()
+ static RootContext ()
{
- tree = new Tree (this);
- TypeManager = new TypeManager ();
+ tree = new Tree ();
+ interface_resolve_order = new ArrayList ();
+ type_container_resolve_order = new ArrayList ();
}
- public Tree Tree {
+ static public Tree Tree {
get {
return tree;
}
}
- public CodeGen CodeGen {
- get {
- return cg;
- }
-
- set {
- //
- // Temporary hack, we should probably
- // intialize `cg' rather than depending on
- // external initialization of it.
- //
- cg = value;
- mb = cg.ModuleBuilder;
- }
+ static public string MainClass;
+
+ public static void RegisterOrder (Interface iface)
+ {
+ interface_resolve_order.Add (iface);
+ }
+
+ public static void RegisterOrder (TypeContainer tc)
+ {
+ type_container_resolve_order.Add (tc);
}
+ public static void RegisterAttribute (TypeContainer tc)
+ {
+ if (attribute_types == null)
+ attribute_types = new ArrayList ();
+
+ attribute_types.Add (tc);
+ }
+
//
// The default compiler checked state
//
- public bool Checked = false;
+ static public bool Checked = false;
- string MakeFQN (string nsn, string name)
+ //
+ // Whether to allow Unsafe code
+ //
+ static public bool Unsafe = false;
+
+ static string MakeFQN (string nsn, string name)
{
string prefix = (nsn == "" ? "" : nsn + ".");
// It creates the TypeBuilder's as it processes the user defined
// types.
// </remarks>
- public void ResolveTree ()
+ static public void ResolveTree ()
{
//
- // Interfaces are processed first, as classes and
+ // Process the attribute types separately and before anything else
+ //
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.DefineType ();
+
+ //
+ // Interfaces are processed next, as classes and
// structs might inherit from an object or implement
// a set of interfaces, we need to be able to tell
// them appart by just using the TypeManager.
//
-
TypeContainer root = Tree.Types;
ArrayList ifaces = root.Interfaces;
if (ifaces != null){
- interface_resolve_order = new ArrayList ();
-
- foreach (Interface i in ifaces) {
- Type t = i.DefineInterface (mb);
- if (t != null)
- interface_resolve_order.Add (i);
- }
+ foreach (Interface i in ifaces)
+ i.DefineType ();
}
-
- type_container_resolve_order = new ArrayList ();
+
- foreach (TypeContainer tc in root.Types) {
- Type t = tc.DefineType (mb);
- if (t != null)
- type_container_resolve_order.Add (tc);
- }
+ foreach (TypeContainer tc in root.Types)
+ tc.DefineType ();
if (root.Delegates != null)
foreach (Delegate d in root.Delegates)
- d.DefineDelegate (mb);
+ d.DefineType ();
if (root.Enums != null)
foreach (Enum e in root.Enums)
- e.DefineEnum (mb);
+ e.DefineType ();
+
+ }
+
+ static void Error_TypeConflict (string name, Location loc)
+ {
+ Report.Error (
+ 520, loc, "`" + name + "' conflicts with a predefined type");
+ }
+
+ static void Error_TypeConflict (string name)
+ {
+ Report.Error (
+ 520, "`" + name + "' conflicts with a predefined type");
+ }
+
+ //
+ // Resolves a single class during the corlib bootstrap process
+ //
+ static TypeBuilder BootstrapCorlib_ResolveClass (TypeContainer root, string name)
+ {
+ object o = root.GetDefinition (name);
+ if (o == null){
+ Report.Error (518, "The predefined type `" + name + "' is not defined");
+ return null;
+ }
+
+ if (!(o is Class)){
+ if (o is DeclSpace){
+ DeclSpace d = (DeclSpace) o;
+
+ Error_TypeConflict (name, d.Location);
+ } else
+ Error_TypeConflict (name);
+
+ return null;
+ }
+
+ return ((DeclSpace) o).DefineType ();
+ }
+
+ //
+ // Resolves a struct during the corlib bootstrap process
+ //
+ static void BootstrapCorlib_ResolveStruct (TypeContainer root, string name)
+ {
+ object o = root.GetDefinition (name);
+ if (o == null){
+ Report.Error (518, "The predefined type `" + name + "' is not defined");
+ return;
+ }
+
+ if (!(o is Struct)){
+ if (o is DeclSpace){
+ DeclSpace d = (DeclSpace) o;
+
+ Error_TypeConflict (name, d.Location);
+ } else
+ Error_TypeConflict (name);
+
+ return;
+ }
+
+ ((DeclSpace) o).DefineType ();
+ }
+
+ //
+ // Resolves a struct during the corlib bootstrap process
+ //
+ static void BootstrapCorlib_ResolveInterface (TypeContainer root, string name)
+ {
+ object o = root.GetDefinition (name);
+ if (o == null){
+ Report.Error (518, "The predefined type `" + name + "' is not defined");
+ return;
+ }
+
+ if (!(o is Interface)){
+ if (o is DeclSpace){
+ DeclSpace d = (DeclSpace) o;
+
+ Error_TypeConflict (name, d.Location);
+ } else
+ Error_TypeConflict (name);
+
+ return;
+ }
+
+ ((DeclSpace) o).DefineType ();
+ }
+
+ //
+ // Resolves a delegate during the corlib bootstrap process
+ //
+ static void BootstrapCorlib_ResolveDelegate (TypeContainer root, string name)
+ {
+ object o = root.GetDefinition (name);
+ if (o == null){
+ Report.Error (518, "The predefined type `" + name + "' is not defined");
+ Environment.Exit (0);
+ }
+
+ if (!(o is Delegate)){
+ Error_TypeConflict (name);
+ return;
+ }
+
+ ((DeclSpace) o).DefineType ();
+ }
+
+
+ /// <summary>
+ /// Resolves the core types in the compiler when compiling with --nostdlib
+ /// </summary>
+ static public void ResolveCore ()
+ {
+ TypeContainer root = Tree.Types;
+
+ TypeManager.object_type = BootstrapCorlib_ResolveClass (root, "System.Object");
+ TypeManager.value_type = BootstrapCorlib_ResolveClass (root, "System.ValueType");
+ TypeManager.attribute_type = BootstrapCorlib_ResolveClass (root, "System.Attribute");
+
+ string [] interfaces_first_stage = {
+ "System.IComparable", "System.ICloneable",
+ "System.IConvertible",
+
+ "System.Collections.IEnumerable",
+ "System.Collections.ICollection",
+ "System.Collections.IEnumerator",
+ "System.Collections.IList",
+ "System.IAsyncResult",
+ "System.IDisposable",
+
+ "System.Runtime.Serialization.ISerializable",
+
+ "System.Reflection.IReflect",
+ "System.Reflection.ICustomAttributeProvider"
+ };
+
+ foreach (string iname in interfaces_first_stage)
+ BootstrapCorlib_ResolveInterface (root, iname);
+
+ //
+ // These are the base value types
+ //
+ string [] structs_first_stage = {
+ "System.Byte", "System.SByte",
+ "System.Int16", "System.UInt16",
+ "System.Int32", "System.UInt32",
+ "System.Int64", "System.UInt64",
+ };
+
+ foreach (string cname in structs_first_stage)
+ BootstrapCorlib_ResolveStruct (root, cname);
+
+ //
+ // Now, we can load the enumerations, after this point,
+ // we can use enums.
+ //
+ TypeManager.InitEnumUnderlyingTypes ();
+
+ string [] structs_second_stage = {
+ "System.Single", "System.Double",
+ "System.Char", "System.Boolean",
+ "System.Decimal", "System.Void",
+ "System.RuntimeFieldHandle",
+ "System.RuntimeTypeHandle",
+ "System.IntPtr"
+ };
+
+ foreach (string cname in structs_second_stage)
+ BootstrapCorlib_ResolveStruct (root, cname);
+ //
+ // These are classes that depends on the core interfaces
+ //
+ string [] classes_second_stage = {
+ "System.Reflection.MemberInfo",
+ "System.Type",
+ "System.Exception",
+
+ //
+ // These are not really important in the order, but they
+ // are used by the compiler later on (typemanager/CoreLookupType-d)
+ //
+ "System.Runtime.CompilerServices.RuntimeHelpers",
+ "System.Reflection.DefaultMemberAttribute",
+ "System.Threading.Monitor",
+
+ "System.AttributeUsageAttribute",
+ "System.Runtime.InteropServices.DllImportAttribute",
+ "System.Runtime.CompilerServices.MethodImplAttribute",
+ "System.Runtime.InteropServices.MarshalAsAttribute",
+ "System.Diagnostics.ConditionalAttribute",
+ "System.ObsoleteAttribute",
+ "System.ParamArrayAttribute",
+ "System.Security.UnverifiableCodeAttribute",
+ "System.Runtime.CompilerServices.IndexerNameAttribute",
+ "System.Runtime.InteropServices.InAttribute"
+ };
+
+ // We must store them here before calling BootstrapCorlib_ResolveDelegate.
+ TypeManager.string_type = BootstrapCorlib_ResolveClass (root, "System.String");
+ TypeManager.enum_type = BootstrapCorlib_ResolveClass (root, "System.Enum");
+ TypeManager.array_type = BootstrapCorlib_ResolveClass (root, "System.Array");
+ TypeManager.multicast_delegate_type = BootstrapCorlib_ResolveClass (root, "System.MulticastDelegate");
+ TypeManager.delegate_type = BootstrapCorlib_ResolveClass (root, "System.Delegate");
+
+ foreach (string cname in classes_second_stage)
+ BootstrapCorlib_ResolveClass (root, cname);
+
+ BootstrapCorlib_ResolveDelegate (root, "System.AsyncCallback");
}
// <summary>
// methods, fields, etc) we need to "Define" them before we
// can save the Assembly
// </remarks>
- public void CloseTypes ()
+ static public void CloseTypes ()
{
TypeContainer root = Tree.Types;
ArrayList ifaces = root.Interfaces;
- if (ifaces != null)
- foreach (Interface i in ifaces)
- i.CloseType ();
+ if (root.Enums != null)
+ foreach (Enum en in root.Enums)
+ en.CloseType ();
+
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.CloseType ();
- foreach (TypeContainer tc in root.Types)
- tc.CloseType ();
+ foreach (Interface iface in interface_resolve_order)
+ iface.CloseType ();
+ //
+ // We do this in two passes, first we close the structs,
+ // then the classes, because it seems the code needs it this
+ // way. If this is really what is going on, we should probably
+ // make sure that we define the structs in order as well.
+ //
+ foreach (TypeContainer tc in type_container_resolve_order){
+ if (tc is Struct && tc.Parent == tree.Types){
+ tc.CloseType ();
+ }
+ }
+
+ foreach (TypeContainer tc in type_container_resolve_order){
+ if (!(tc is Struct && tc.Parent == tree.Types))
+ tc.CloseType ();
+ }
+
if (root.Delegates != null)
foreach (Delegate d in root.Delegates)
- d.CloseDelegate ();
+ d.CloseType ();
- if (root.Enums != null)
- foreach (Enum en in root.Enums)
- en.CloseEnum ();
-
//
// If we have a <PrivateImplementationDetails> class, close it
impl_details_class.CreateType ();
}
}
-
+
//
- // Public function used to locate types, this can only
- // be used after the ResolveTree function has been invoked.
+ // This idea is from Felix Arrese-Igor
//
- // Returns: Type or null if they type can not be found.
+ // Returns : the implicit parent of a composite namespace string
+ // eg. Implicit parent of A.B is A
//
- public Type LookupType (DeclSpace ds, string name, bool silent)
+ static public string ImplicitParent (string ns)
{
- Type t;
-
- t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
- if (t != null)
- return t;
+ int i = ns.LastIndexOf (".");
+ if (i < 0)
+ return null;
+
+ return ns.Substring (0, i);
+ }
+ static Type NamespaceLookup (Namespace curr_ns, string name, Location loc)
+ {
+ Type t;
+
+ //
+ // Try in the current namespace and all its implicit parents
+ //
+ for (string ns = curr_ns.Name; ns != null; ns = ImplicitParent (ns)) {
+ t = TypeManager.LookupType (MakeFQN (ns, name));
+ if (t != null)
+ return t;
+ }
+
+ //
// It's possible that name already is fully qualified. So we do
// a simple direct lookup without adding any namespace names
-
+ //
t = TypeManager.LookupType (name);
if (t != null)
return t;
+
+ //
+ // Try the aliases in the current namespace
+ //
+ string alias = curr_ns.LookupAlias (name);
+
+ if (alias != null) {
+ t = TypeManager.LookupType (alias);
+ if (t != null)
+ return t;
+
+ t = TypeManager.LookupType (MakeFQN (alias, name));
+ if (t != null)
+ return t;
+ }
- for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
+ for (Namespace ns = curr_ns; ns != null; ns = ns.Parent) {
+ //
+ // Look in the namespace ns
+ //
+ t = TypeManager.LookupType (MakeFQN (ns.Name, name));
+ if (t != null)
+ return t;
+
+ //
+ // Then try with the using clauses
+ //
ArrayList using_list = ns.UsingTable;
if (using_list == null)
continue;
- foreach (string n in using_list){
- t = TypeManager.LookupType (MakeFQN (n, name));
+ Type match = null;
+ foreach (Namespace.UsingEntry ue in using_list) {
+ match = TypeManager.LookupType (MakeFQN (ue.Name, name));
+ if (match != null){
+ if (t != null){
+ DeclSpace.Error_AmbiguousTypeReference (loc, name, t, match);
+ return null;
+ }
+
+ t = match;
+ ue.Used = true;
+ }
+ }
+ if (t != null)
+ return t;
+
+ //
+ // Try with aliases
+ //
+ string a = ns.LookupAlias (name);
+ if (a != null) {
+ t = TypeManager.LookupType (a);
+ if (t != null)
+ return t;
+
+ t = TypeManager.LookupType (MakeFQN (a, name));
if (t != null)
return t;
}
}
- // For the case the type we are looking for is nested within this one.
- t = TypeManager.LookupType (ds.Name + "." + name);
- if (t != null)
- return t;
-
+ return null;
+ }
+
+ //
+ // Public function used to locate types, this can only
+ // be used after the ResolveTree function has been invoked.
+ //
+ // Returns: Type or null if they type can not be found.
+ //
+ // Come to think of it, this should be a DeclSpace
+ //
+ static public Type LookupType (DeclSpace ds, string name, bool silent, Location loc)
+ {
+ Type t;
+
+ if (ds.Cache.Contains (name)){
+ t = (Type) ds.Cache [name];
+ if (t != null)
+ return t;
+ } else {
+ //
+ // For the case the type we are looking for is nested within this one
+ // or is in any base class
+ //
+ DeclSpace containing_ds = ds;
+ while (containing_ds != null){
+ Type current_type = containing_ds.TypeBuilder;
+
+ while (current_type != null) {
+ //
+ // nested class
+ //
+ t = TypeManager.LookupType (current_type.FullName + "." + name);
+ if (t != null){
+ ds.Cache [name] = t;
+ return t;
+ }
+
+ current_type = current_type.BaseType;
+ }
+
+ containing_ds = containing_ds.Parent;
+ }
+
+ t = NamespaceLookup (ds.Namespace, name, loc);
+ if (t != null){
+ ds.Cache [name] = t;
+ return t;
+ }
+ }
+
if (!silent)
- Report.Error (246, "Cannot find type `"+name+"'");
+ Report.Error (246, loc, "Cannot find type `"+name+"'");
return null;
}
// This is the silent version of LookupType, you can use this
// to `probe' for a type
// </summary>
- public Type LookupType (TypeContainer tc, string name)
+ static public Type LookupType (TypeContainer tc, string name, Location loc)
{
- return LookupType (tc, name, true);
+ return LookupType (tc, name, true, loc);
}
- public bool IsNamespace (string name)
+ static public bool IsNamespace (string name)
{
Namespace ns;
return false;
}
+ static void Report1530 (Location loc)
+ {
+ Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
+ }
+
+ static public void PopulateCoreType (TypeContainer root, string name)
+ {
+ DeclSpace ds = (DeclSpace) root.GetDefinition (name);
+
+ ds.DefineMembers (root);
+ ds.Define (root);
+ }
+
+ static public void BootCorlib_PopulateCoreTypes ()
+ {
+ TypeContainer root = tree.Types;
+
+ PopulateCoreType (root, "System.Object");
+ PopulateCoreType (root, "System.ValueType");
+ PopulateCoreType (root, "System.Attribute");
+ }
+
// <summary>
// Populates the structs and classes with fields and methods
// </summary>
//
// This is invoked after all interfaces, structs and classes
// have been defined through `ResolveTree'
- public void PopulateTypes ()
+ static public void PopulateTypes ()
{
- if (interface_resolve_order != null)
+ TypeContainer root = Tree.Types;
+
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.DefineMembers (root);
+
+ if (interface_resolve_order != null){
foreach (Interface iface in interface_resolve_order)
- iface.Populate ();
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.DefineMembers (root);
+ else
+ Report1530 (iface.Location);
+ }
- if (type_container_resolve_order != null)
- foreach (TypeContainer tc in type_container_resolve_order)
- tc.Populate ();
- TypeContainer root = Tree.Types;
+ if (type_container_resolve_order != null){
+ if (RootContext.StdLib){
+ foreach (TypeContainer tc in type_container_resolve_order) {
+ if ((tc.ModFlags & Modifiers.NEW) == 0)
+ tc.DefineMembers (root);
+ else
+ Report1530 (tc.Location);
+ }
+ } else {
+ foreach (TypeContainer tc in type_container_resolve_order) {
+ // When compiling corlib, these types have already been
+ // populated from BootCorlib_PopulateCoreTypes ().
+ if (((tc.Name == "System.Object") ||
+ (tc.Name == "System.Attribute") ||
+ (tc.Name == "System.ValueType")))
+ continue;
+
+ if ((tc.ModFlags & Modifiers.NEW) == 0)
+ tc.DefineMembers (root);
+ else
+ Report1530 (tc.Location);
+ }
+ }
+ }
ArrayList delegates = root.Delegates;
- if (delegates != null)
+ if (delegates != null){
foreach (Delegate d in delegates)
- d.Populate (root);
+ if ((d.ModFlags & Modifiers.NEW) == 0)
+ d.DefineMembers (root);
+ else
+ Report1530 (d.Location);
+ }
ArrayList enums = root.Enums;
- if (enums != null)
+ if (enums != null){
foreach (Enum en in enums)
- en.Populate (root);
-
+ if ((en.ModFlags & Modifiers.NEW) == 0)
+ en.DefineMembers (root);
+ else
+ Report1530 (en.Location);
+ }
}
- public void EmitCode ()
+ static public void DefineTypes ()
{
- if (type_container_resolve_order != null)
- foreach (TypeContainer tc in type_container_resolve_order)
- tc.Emit ();
- }
-
- // <summary>
- // Compiling against Standard Libraries property.
- // </summary>
- public bool StdLib {
- get {
- return stdlib;
+ TypeContainer root = Tree.Types;
+
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.Define (root);
+
+ if (interface_resolve_order != null){
+ foreach (Interface iface in interface_resolve_order)
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.Define (root);
}
- set {
- stdlib = value;
+
+ if (type_container_resolve_order != null){
+ foreach (TypeContainer tc in type_container_resolve_order) {
+ // When compiling corlib, these types have already been
+ // populated from BootCorlib_PopulateCoreTypes ().
+ if (!RootContext.StdLib &&
+ ((tc.Name == "System.Object") ||
+ (tc.Name == "System.Attribute") ||
+ (tc.Name == "System.ValueType")))
+ continue;
+
+ if ((tc.ModFlags & Modifiers.NEW) == 0)
+ tc.Define (root);
+ }
}
- }
- public static ModuleBuilder ModuleBuilder {
- get {
- return mb;
+ ArrayList delegates = root.Delegates;
+ if (delegates != null){
+ foreach (Delegate d in delegates)
+ if ((d.ModFlags & Modifiers.NEW) == 0)
+ d.Define (root);
+ }
+
+ ArrayList enums = root.Enums;
+ if (enums != null){
+ foreach (Enum en in enums)
+ if ((en.ModFlags & Modifiers.NEW) == 0)
+ en.Define (root);
}
}
+ static public void EmitCode ()
+ {
+ //
+ // Because of the strange way in which we do things, global
+ // attributes must be processed first.
+ //
+ if (global_attributes.Count > 0){
+ AssemblyBuilder ab = CodeGen.AssemblyBuilder;
+ TypeContainer dummy = new TypeContainer (null, "", new Location (-1));
+ EmitContext temp_ec = new EmitContext (
+ dummy, Mono.CSharp.Location.Null, null, null, 0, false);
+
+ foreach (DictionaryEntry de in global_attributes){
+ Namespace ns = (Namespace) de.Key;
+ Attributes attrs = (Attributes) de.Value;
+
+ dummy.Namespace = ns;
+ Attribute.ApplyAttributes (temp_ec, ab, ab, attrs);
+ }
+ }
+
+ if (attribute_types != null)
+ foreach (TypeContainer tc in attribute_types)
+ tc.Emit ();
+
+ if (type_container_resolve_order != null) {
+ foreach (TypeContainer tc in type_container_resolve_order)
+ tc.EmitConstants ();
+
+ foreach (TypeContainer tc in type_container_resolve_order)
+ tc.Emit ();
+ }
+
+ if (Unsafe) {
+ if (TypeManager.unverifiable_code_ctor == null) {
+ Console.WriteLine ("Internal error ! Cannot set unverifiable code attribute.");
+ return;
+ }
+
+ CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor,
+ new object [0]);
+ CodeGen.ModuleBuilder.SetCustomAttribute (cb);
+ }
+ }
+
//
// Public Field, used to track which method is the public entry
// point.
//
- public MethodInfo EntryPoint;
+ static public MethodInfo EntryPoint;
+
+ //
+ // Track the location of the entry point.
+ //
+ static public Location EntryPointLocation;
//
// These are used to generate unique names on the structs and fields.
//
- int field_count;
+ static int field_count;
//
// Makes an initialized struct, returns the field builder that
//
// 2. Define the field on the impl_details_class
//
- public FieldBuilder MakeStaticData (byte [] data)
+ static public FieldBuilder MakeStaticData (byte [] data)
{
FieldBuilder fb;
int size = data.Length;
if (impl_details_class == null)
- impl_details_class = mb.DefineType (
- "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
+ impl_details_class = CodeGen.ModuleBuilder.DefineType (
+ "<PrivateImplementationDetails>", TypeAttributes.NotPublic, TypeManager.object_type);
fb = impl_details_class.DefineInitializedData (
"$$field-" + (field_count++), data,
return fb;
}
+
+ //
+ // Adds a global attribute that was declared in `container',
+ // the attribute is in `attr', and it was defined at `loc'
+ //
+ static public void AddGlobalAttributeSection (TypeContainer container, AttributeSection attr)
+ {
+ Namespace ns = container.Namespace;
+ Attributes a = (Attributes) global_attributes [ns];
+
+ if (a == null)
+ global_attributes [ns] = new Attributes (attr);
+ else
+ a.AddAttributeSection (attr);
+ }
}
}