Facilitate the merge
[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, 0)
33                 {
34                         this.assembly = assembly;
35                 }
36
37                 public override 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 List<TypeContainer> ();
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, MethodSpec ctor, byte[] cdata, 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 ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
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                                 TypeSpec t = TypeManager.CoreLookupType (context, "System.Security", "UnverifiableCodeAttribute", MemberKind.Class, true);
151                                 if (t != null) {
152                                         var unverifiable_code_ctor = TypeManager.GetPredefinedConstructor (t, Location.Null, TypeSpec.EmptyTypes);
153                                         if (unverifiable_code_ctor != null)
154                                                 builder.SetCustomAttribute (new CustomAttributeBuilder ((ConstructorInfo) unverifiable_code_ctor.GetMetaInfo (), 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 bool HasDefaultCharSet {
180                         get {
181                                 return has_default_charset;
182                         }
183                 }
184
185                 public override string GetSignatureForError ()
186                 {
187                         return "<module>";
188                 }
189
190                 public override bool IsClsComplianceRequired ()
191                 {
192                         return CodeGen.Assembly.IsClsCompliant;
193                 }
194
195                 protected override bool AddMemberType (TypeContainer ds)
196                 {
197                         if (!AddToContainer (ds, ds.Name))
198                                 return false;
199                         ds.NamespaceEntry.NS.AddType (ds.Definition);
200                         return true;
201                 }
202
203                 protected override void RemoveMemberType (DeclSpace ds)
204                 {
205                         ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename);
206                         base.RemoveMemberType (ds);
207                 }
208
209                 /// <summary>
210                 /// It is called very early therefore can resolve only predefined attributes
211                 /// </summary>
212                 public void Resolve ()
213                 {
214                         if (OptAttributes == null)
215                                 return;
216
217                         if (!OptAttributes.CheckTargets ())
218                                 return;
219
220                         Attribute a = ResolveAttribute (Compiler.PredefinedAttributes.DefaultCharset);
221                         if (a != null) {
222                                 has_default_charset = true;
223                                 DefaultCharSet = a.GetCharSetValue ();
224                                 switch (DefaultCharSet) {
225                                 case CharSet.Ansi:
226                                 case CharSet.None:
227                                         break;
228                                 case CharSet.Auto:
229                                         DefaultCharSetType = TypeAttributes.AutoClass;
230                                         break;
231                                 case CharSet.Unicode:
232                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
233                                         break;
234                                 default:
235                                         Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
236                                         break;
237                                 }
238                         }
239                 }
240
241                 Attribute ResolveAttribute (PredefinedAttribute a_type)
242                 {
243                         Attribute a = OptAttributes.Search (a_type);
244                         if (a != null) {
245                                 a.Resolve ();
246                         }
247                         return a;
248                 }
249
250                 public override string[] ValidAttributeTargets {
251                         get {
252                                 return attribute_targets;
253                         }
254                 }
255         }
256
257         class RootDeclSpace : TypeContainer {
258                 public RootDeclSpace (NamespaceEntry ns)
259                         : base (ns, null, MemberName.Null, null, 0)
260                 {
261                         PartialContainer = RootContext.ToplevelTypes;
262                 }
263
264                 public override AttributeTargets AttributeTargets {
265                         get { throw new InternalErrorException ("should not be called"); }
266                 }
267
268                 public override CompilerContext Compiler {
269                         get {
270                                 return PartialContainer.Compiler;
271                         }
272                 }
273
274                 public override string DocCommentHeader {
275                         get { throw new InternalErrorException ("should not be called"); }
276                 }
277
278                 //public override bool Define ()
279                 //{
280                 //    throw new InternalErrorException ("should not be called");
281                 //}
282
283                 public override TypeBuilder DefineType ()
284                 {
285                         throw new InternalErrorException ("should not be called");
286                 }
287
288                 public override ModuleContainer Module {
289                         get {
290                                 return PartialContainer.Module;
291                         }
292                 }
293
294                 public override bool IsClsComplianceRequired ()
295                 {
296                         return PartialContainer.IsClsComplianceRequired ();
297                 }
298
299                 public override FullNamedExpression LookupNamespaceAlias (string name)
300                 {
301                         return NamespaceEntry.LookupNamespaceAlias (name);
302                 }
303         }
304 }