2009-12-03 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.Generic;
15 using System.Reflection;
16 using System.Reflection.Emit;
17 using System.Runtime.InteropServices;
18
19 namespace Mono.CSharp
20 {
21         //
22         // Module container, it can be used as a top-level type
23         //
24         public class ModuleContainer : TypeContainer
25         {
26                 public CharSet DefaultCharSet = CharSet.Ansi;
27                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
28
29                 protected Assembly assembly;
30
31                 public ModuleContainer (Assembly assembly)
32                         : base (null, null, MemberName.Null, null, Kind.Root)
33                 {
34                         this.assembly = assembly;
35                 }
36
37                 public Assembly Assembly {
38                         get { return assembly; }
39                 }
40
41                 // FIXME: Remove this evil one day
42                 public ModuleCompiled Compiled {
43                         get { return (ModuleCompiled) this; }
44                 }
45
46                 public override ModuleContainer Module {
47                         get {
48                                 return this;
49                         }
50                 }
51         }
52
53         //
54         // Compiled top-level types
55         //
56         public class ModuleCompiled : ModuleContainer
57         {
58                 Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
59                 readonly bool is_unsafe;
60                 readonly CompilerContext context;
61
62                 ModuleBuilder builder;
63
64                 bool has_default_charset;
65
66                 static readonly string[] attribute_targets = new string[] { "module" };
67
68                 public ModuleCompiled (CompilerContext context, bool isUnsafe)
69                         : base (null)
70                 {
71                         this.is_unsafe = isUnsafe;
72                         this.context = context;
73
74                         types = new MemberCoreArrayList ();
75                         anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
76                 }
77
78                 public override AttributeTargets AttributeTargets {
79                         get {
80                                 return AttributeTargets.Module;
81                         }
82                 }
83
84                 public void AddAnonymousType (AnonymousTypeClass type)
85                 {
86                         List<AnonymousTypeClass> existing;
87                         if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
88                         if (existing == null) {
89                                 existing = new List<AnonymousTypeClass> ();
90                                 anonymous_types.Add (type.Parameters.Count, existing);
91                         }
92
93                         existing.Add (type);
94                 }
95
96                 public void AddAttributes (List<Attribute> attrs)
97                 {
98                         foreach (Attribute a in attrs)
99                                 a.AttachTo (this, CodeGen.Assembly);
100
101                         if (attributes == null) {
102                                 attributes = new Attributes (attrs);
103                                 return;
104                         }
105
106                         attributes.AddAttributes (attrs);
107                 }
108
109                 public override TypeContainer AddPartial (TypeContainer nextPart)
110                 {
111                         return AddPartial (nextPart, nextPart.Name);
112                 }
113
114                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
115                 {
116                         if (a.Type == pa.CLSCompliant) {
117                                 if (CodeGen.Assembly.ClsCompliantAttribute == null) {
118                                         Report.Warning (3012, 1, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
119                                 } else if (CodeGen.Assembly.IsClsCompliant != a.GetBoolean ()) {
120                                         Report.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.GetSignatureForError ());
121                                         Report.Warning (3017, 1, a.Location, "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
122                                         return;
123                                 }
124                         }
125
126                         builder.SetCustomAttribute (cb);
127                 }
128
129                 public ModuleBuilder Builder {
130                         get {
131                                 return builder;
132                         }
133
134                         set {
135                                 builder = value;
136                                 assembly = builder.Assembly;
137                         }
138                 }
139
140                 public override CompilerContext Compiler {
141                         get { return context; }
142                 }
143
144                 public override void Emit ()
145                 {
146                         if (OptAttributes != null)
147                                 OptAttributes.Emit ();
148
149                         if (is_unsafe) {
150                                 Type t = TypeManager.CoreLookupType (context, "System.Security", "UnverifiableCodeAttribute", Kind.Class, true);
151                                 if (t != null) {
152                                         ConstructorInfo unverifiable_code_ctor = TypeManager.GetPredefinedConstructor (t, Location.Null, Type.EmptyTypes);
153                                         if (unverifiable_code_ctor != null)
154                                                 builder.SetCustomAttribute (new CustomAttributeBuilder (unverifiable_code_ctor, new object [0]));
155                                 }
156                         }
157                 }
158
159                 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
160                 {
161                         List<AnonymousTypeClass> candidates;
162                         if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
163                                 return null;
164
165                         int i;
166                         foreach (AnonymousTypeClass at in candidates) {
167                                 for (i = 0; i < parameters.Count; ++i) {
168                                         if (!parameters [i].Equals (at.Parameters [i]))
169                                                 break;
170                                 }
171
172                                 if (i == parameters.Count)
173                                         return at;
174                         }
175
176                         return null;
177                 }
178
179                 public override bool GetClsCompliantAttributeValue ()
180                 {
181                         return CodeGen.Assembly.IsClsCompliant;
182                 }
183
184                 public bool HasDefaultCharSet {
185                         get {
186                                 return has_default_charset;
187                         }
188                 }
189
190                 public override string GetSignatureForError ()
191                 {
192                         return "<module>";
193                 }
194
195                 public override bool IsClsComplianceRequired ()
196                 {
197                         return true;
198                 }
199
200                 protected override bool AddMemberType (DeclSpace ds)
201                 {
202                         if (!AddToContainer (ds, ds.Name))
203                                 return false;
204                         ds.NamespaceEntry.NS.AddDeclSpace (ds.Basename, ds);
205                         return true;
206                 }
207
208                 protected override void RemoveMemberType (DeclSpace ds)
209                 {
210                         ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
211                         base.RemoveMemberType (ds);
212                 }
213
214                 /// <summary>
215                 /// It is called very early therefore can resolve only predefined attributes
216                 /// </summary>
217                 public void Resolve ()
218                 {
219                         if (OptAttributes == null)
220                                 return;
221
222                         if (!OptAttributes.CheckTargets ())
223                                 return;
224
225                         Attribute a = ResolveAttribute (PredefinedAttributes.Get.DefaultCharset);
226                         if (a != null) {
227                                 has_default_charset = true;
228                                 DefaultCharSet = a.GetCharSetValue ();
229                                 switch (DefaultCharSet) {
230                                 case CharSet.Ansi:
231                                 case CharSet.None:
232                                         break;
233                                 case CharSet.Auto:
234                                         DefaultCharSetType = TypeAttributes.AutoClass;
235                                         break;
236                                 case CharSet.Unicode:
237                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
238                                         break;
239                                 default:
240                                         Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
241                                         break;
242                                 }
243                         }
244                 }
245
246                 Attribute ResolveAttribute (PredefinedAttribute a_type)
247                 {
248                         Attribute a = OptAttributes.Search (a_type);
249                         if (a != null) {
250                                 a.Resolve ();
251                         }
252                         return a;
253                 }
254
255                 public override string[] ValidAttributeTargets {
256                         get {
257                                 return attribute_targets;
258                         }
259                 }
260         }
261
262         class RootDeclSpace : DeclSpace {
263                 public RootDeclSpace (NamespaceEntry ns)
264                         : base (ns, null, MemberName.Null, null)
265                 {
266                         PartialContainer = RootContext.ToplevelTypes;
267                 }
268
269                 public override AttributeTargets AttributeTargets {
270                         get { throw new InternalErrorException ("should not be called"); }
271                 }
272
273                 public override CompilerContext Compiler {
274                         get {
275                                 return PartialContainer.Compiler;
276                         }
277                 }
278
279                 public override string DocCommentHeader {
280                         get { throw new InternalErrorException ("should not be called"); }
281                 }
282
283                 public override bool Define ()
284                 {
285                         throw new InternalErrorException ("should not be called");
286                 }
287
288                 public override TypeBuilder DefineType ()
289                 {
290                         throw new InternalErrorException ("should not be called");
291                 }
292
293                 public override MemberCache MemberCache {
294                         get { return PartialContainer.MemberCache; }
295                 }
296
297                 public override ModuleContainer Module {
298                         get {
299                                 return PartialContainer.Module;
300                         }
301                 }
302
303                 public override bool GetClsCompliantAttributeValue ()
304                 {
305                         return PartialContainer.GetClsCompliantAttributeValue ();
306                 }
307
308                 public override bool IsClsComplianceRequired ()
309                 {
310                         return PartialContainer.IsClsComplianceRequired ();
311                 }
312
313                 public override FullNamedExpression LookupNamespaceAlias (string name)
314                 {
315                         return NamespaceEntry.LookupNamespaceAlias (name);
316                 }
317         }
318 }