2009-03-17 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / roottypes.cs
1 //
2 // roottypes.cs: keeps a tree representation of the generated code
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Marek Safar  (marek.safar@gmail.com)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 //
12
13 using System;
14 using System.Collections;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Runtime.InteropServices;
18
19 namespace Mono.CSharp
20 {
21         //
22         // Compiled top-level types
23         //
24         public sealed class ModuleContainer : TypeContainer
25         {
26                 // TODO: It'd be so nice to have generics
27                 Hashtable anonymous_types;
28                 public ModuleBuilder Builder;
29                 bool is_unsafe;
30
31 #if GMCS_SOURCE
32                 bool has_default_charset;
33 #endif
34
35                 public CharSet DefaultCharSet = CharSet.Ansi;
36                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
37
38                 static readonly string[] attribute_targets = new string[] { "module" };
39
40                 public ModuleContainer (bool isUnsafe)
41                         : base (null, null, MemberName.Null, null, Kind.Root)
42                 {
43                         this.is_unsafe = isUnsafe;
44                         types = new ArrayList ();
45                         anonymous_types = new Hashtable ();
46                 }
47
48                 public override AttributeTargets AttributeTargets {
49                         get {
50                                 return AttributeTargets.Module;
51                         }
52                 }
53
54                 public void AddAnonymousType (AnonymousTypeClass type)
55                 {
56                         ArrayList existing = (ArrayList)anonymous_types [type.Parameters.Count];
57                         if (existing == null) {
58                                 existing = new ArrayList ();
59                                 anonymous_types.Add (type.Parameters.Count, existing);
60                         }
61                         existing.Add (type);
62                 }
63
64                 public void AddAttributes (ArrayList attrs)
65                 {
66                         foreach (Attribute a in attrs)
67                                 a.AttachTo (this);
68
69                         if (attributes == null) {
70                                 attributes = new Attributes (attrs);
71                                 return;
72                         }
73
74                         attributes.AddAttributes (attrs);
75                 }
76
77                 public override TypeContainer AddPartial (TypeContainer nextPart)
78                 {
79                         return AddPartial (nextPart, nextPart.Name);
80                 }
81
82                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
83                 {
84                         if (a.Type == pa.CLSCompliant) {
85                                 if (CodeGen.Assembly.ClsCompliantAttribute == null) {
86                                         Report.Warning (3012, 1, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
87                                 } else if (CodeGen.Assembly.IsClsCompliant != a.GetBoolean ()) {
88                                         Report.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.GetSignatureForError ());
89                                         Report.Warning (3017, 1, a.Location, "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
90                                         return;
91                                 }
92                         }
93
94                         Builder.SetCustomAttribute (cb);
95                 }
96
97                 public override void Emit ()
98                 {
99                         if (OptAttributes != null)
100                                 OptAttributes.Emit ();
101
102                         if (is_unsafe) {
103                                 Type t = TypeManager.CoreLookupType ("System.Security", "UnverifiableCodeAttribute", Kind.Class, true);
104                                 if (t != null) {
105                                         ConstructorInfo unverifiable_code_ctor = TypeManager.GetPredefinedConstructor (t, Location.Null, Type.EmptyTypes);
106                                         if (unverifiable_code_ctor != null)
107                                                 Builder.SetCustomAttribute (new CustomAttributeBuilder (unverifiable_code_ctor, new object [0]));
108                                 }
109                         }
110                 }
111
112                 public AnonymousTypeClass GetAnonymousType (ArrayList parameters)
113                 {
114                         ArrayList candidates = (ArrayList) anonymous_types [parameters.Count];
115                         if (candidates == null)
116                                 return null;
117
118                         int i;
119                         foreach (AnonymousTypeClass at in candidates) {
120                                 for (i = 0; i < parameters.Count; ++i) {
121                                         if (!parameters [i].Equals (at.Parameters [i]))
122                                                 break;
123                                 }
124
125                                 if (i == parameters.Count)
126                                         return at;
127                         }
128
129                         return null;
130                 }
131
132                 public override bool GetClsCompliantAttributeValue ()
133                 {
134                         return CodeGen.Assembly.IsClsCompliant;
135                 }
136
137                 public bool HasDefaultCharSet {
138                         get {
139 #if GMCS_SOURCE         
140                                 return has_default_charset;
141 #else
142                                 return false;
143 #endif                                                          
144                         }
145                 }
146
147                 public override string GetSignatureForError ()
148                 {
149                         return "<module>";
150                 }
151
152                 public override bool IsClsComplianceRequired ()
153                 {
154                         return true;
155                 }
156
157                 public override ModuleContainer Module {
158                         get {
159                                 return this;
160                         }
161                 }
162
163                 public override IResolveContext ResolveContext {
164                         get { return this; }
165                 }
166
167                 protected override bool AddMemberType (DeclSpace ds)
168                 {
169                         if (!AddToContainer (ds, ds.Name))
170                                 return false;
171                         ds.NamespaceEntry.NS.AddDeclSpace (ds.Basename, ds);
172                         return true;
173                 }
174
175                 protected override void RemoveMemberType (DeclSpace ds)
176                 {
177                         ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
178                         base.RemoveMemberType (ds);
179                 }
180
181                 /// <summary>
182                 /// It is called very early therefore can resolve only predefined attributes
183                 /// </summary>
184                 public void Resolve ()
185                 {
186 #if GMCS_SOURCE
187                         if (OptAttributes == null)
188                                 return;
189
190                         if (!OptAttributes.CheckTargets ())
191                                 return;
192
193                         Attribute a = ResolveAttribute (PredefinedAttributes.Get.DefaultCharset);
194                         if (a != null) {
195                                 has_default_charset = true;
196                                 DefaultCharSet = a.GetCharSetValue ();
197                                 switch (DefaultCharSet) {
198                                 case CharSet.Ansi:
199                                 case CharSet.None:
200                                         break;
201                                 case CharSet.Auto:
202                                         DefaultCharSetType = TypeAttributes.AutoClass;
203                                         break;
204                                 case CharSet.Unicode:
205                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
206                                         break;
207                                 default:
208                                         Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
209                                         break;
210                                 }
211                         }
212 #endif
213                 }
214
215                 Attribute ResolveAttribute (PredefinedAttribute a_type)
216                 {
217                         Attribute a = OptAttributes.Search (a_type);
218                         if (a != null) {
219                                 a.Resolve ();
220                         }
221                         return a;
222                 }
223
224                 public override string[] ValidAttributeTargets {
225                         get {
226                                 return attribute_targets;
227                         }
228                 }
229         }
230
231         class RootDeclSpace : DeclSpace {
232                 public RootDeclSpace (NamespaceEntry ns)
233                         : base (ns, null, MemberName.Null, null)
234                 {
235                         PartialContainer = RootContext.ToplevelTypes;
236                 }
237
238                 public override AttributeTargets AttributeTargets {
239                         get { throw new InternalErrorException ("should not be called"); }
240                 }
241
242                 public override string DocCommentHeader {
243                         get { throw new InternalErrorException ("should not be called"); }
244                 }
245
246                 public override bool Define ()
247                 {
248                         throw new InternalErrorException ("should not be called");
249                 }
250
251                 public override TypeBuilder DefineType ()
252                 {
253                         throw new InternalErrorException ("should not be called");
254                 }
255
256                 public override MemberCache MemberCache {
257                         get { return PartialContainer.MemberCache; }
258                 }
259
260                 public override ModuleContainer Module {
261                         get {
262                                 return PartialContainer.Module;
263                         }
264                 }
265
266                 public override bool GetClsCompliantAttributeValue ()
267                 {
268                         return PartialContainer.GetClsCompliantAttributeValue ();
269                 }
270
271                 public override bool IsClsComplianceRequired ()
272                 {
273                         return PartialContainer.IsClsComplianceRequired ();
274                 }
275         }
276 }