X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fgmcs%2Fcodegen.cs;h=7f5d62efb21963cc23558a1e2ba0159949972416;hb=cffda3181a45b81bbf989a128da6f7a5047a6a99;hp=71f4a9dafdb20f79a84c694bf9496fee576f1104;hpb=dac1a705ea8721eeff8b2a91da1747d04706f0bb;p=mono.git diff --git a/mcs/gmcs/codegen.cs b/mcs/gmcs/codegen.cs old mode 100755 new mode 100644 index 71f4a9dafdb..7f5d62efb21 --- a/mcs/gmcs/codegen.cs +++ b/mcs/gmcs/codegen.cs @@ -4,16 +4,20 @@ // Author: // Miguel de Icaza (miguel@ximian.com) // -// (C) 2001 Ximian, Inc. +// (C) 2001, 2002, 2003 Ximian, Inc. +// (C) 2004 Novell, Inc. // - +//#define PRODUCTION using System; using System.IO; using System.Collections; +using System.Collections.Specialized; using System.Reflection; using System.Reflection.Emit; using System.Runtime.InteropServices; +using System.Security; using System.Security.Cryptography; +using System.Security.Permissions; using Mono.Security.Cryptography; @@ -75,16 +79,16 @@ namespace Mono.CSharp { // // Initializes the symbol writer // - static void InitializeSymbolWriter () + static void InitializeSymbolWriter (string filename) { - SymbolWriter = SymbolWriter.GetSymbolWriter (Module.Builder); + SymbolWriter = SymbolWriter.GetSymbolWriter (Module.Builder, filename); // // If we got an ISymbolWriter instance, initialize it. // if (SymbolWriter == null) { Report.Warning ( - -18, "Could not find the symbol writer assembly (Mono.CSharp.Debugger.dll). This is normally an installation problem. Please make sure to compile and install the mcs/class/Mono.CSharp.Debugger directory."); + -18, "Could not find the symbol writer assembly (Mono.CompilerServices.SymbolWriter.dll). This is normally an installation problem. Please make sure to compile and install the mcs/class/Mono.CompilerServices.SymbolWriter directory."); return; } } @@ -145,10 +149,10 @@ namespace Mono.CSharp { // load the default symbol writer. // Module.Builder = Assembly.Builder.DefineDynamicModule ( - Basename (name), Basename (output), want_debugging_support); + Basename (name), Basename (output), false); if (want_debugging_support) - InitializeSymbolWriter (); + InitializeSymbolWriter (output); } static public void Save (string name) @@ -168,6 +172,9 @@ namespace Mono.CSharp { catch (System.IO.IOException io) { Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message); } + + if (SymbolWriter != null) + SymbolWriter.WriteSymbolFile (); } } @@ -178,7 +185,6 @@ namespace Mono.CSharp { // variable mapping. // public class VariableStorage { - ILGenerator ig; FieldBuilder fb; LocalBuilder local; @@ -188,19 +194,18 @@ namespace Mono.CSharp { { count++; if (ec.InIterator) - fb = IteratorHandler.Current.MapVariable ("s_", count.ToString (), t); + fb = ec.CurrentIterator.MapVariable ("s_", count.ToString (), t); else local = ec.ig.DeclareLocal (t); - ig = ec.ig; } - public void EmitThis () + public void EmitThis (ILGenerator ig) { if (fb != null) ig.Emit (OpCodes.Ldarg_0); } - public void EmitStore () + public void EmitStore (ILGenerator ig) { if (fb == null) ig.Emit (OpCodes.Stloc, local); @@ -208,22 +213,30 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Stfld, fb); } - public void EmitLoad () + public void EmitLoad (ILGenerator ig) { if (fb == null) ig.Emit (OpCodes.Ldloc, local); else ig.Emit (OpCodes.Ldfld, fb); } + + public void EmitLoadAddress (ILGenerator ig) + { + if (fb == null) + ig.Emit (OpCodes.Ldloca, local); + else + ig.Emit (OpCodes.Ldflda, fb); + } - public void EmitCall (MethodInfo mi) + public void EmitCall (ILGenerator ig, MethodInfo mi) { // FIXME : we should handle a call like tostring // here, where boxing is needed. However, we will // never encounter that with the current usage. bool value_type_call; - EmitThis (); + EmitThis (ig); if (fb == null) { value_type_call = local.LocalType.IsValueType; @@ -358,7 +371,7 @@ namespace Mono.CSharp { /// /// Whether we are inside an anonymous method. /// - public bool InAnonymousMethod; + public AnonymousMethod CurrentAnonymousMethod; /// /// Location for this EmitContext @@ -382,6 +395,35 @@ namespace Mono.CSharp { /// public bool InEnumContext; + /// + /// Anonymous methods can capture local variables and fields, + /// this object tracks it. It is copied from the TopLevelBlock + /// field. + /// + public CaptureContext capture_context; + + /// + /// Trace when method is called and is obsolete then this member suppress message + /// when call is inside next [Obsolete] method or type. + /// + public bool TestObsoleteMethodUsage = true; + + /// + /// The current iterator + /// + public Iterator CurrentIterator; + + /// + /// Whether we are in the resolving stage or not + /// + enum Phase { + Created, + Resolving, + Emitting + } + + Phase current_phase; + FlowBranching current_flow_branching; public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig, @@ -393,6 +435,9 @@ namespace Mono.CSharp { DeclSpace = ds; CheckState = RootContext.Checked; ConstantCheckState = true; + + if ((return_type is TypeBuilder) && return_type.IsGenericTypeDefinition) + throw new Exception ("FUCK"); IsStatic = (code_flags & Modifiers.STATIC) != 0; InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0; @@ -401,6 +446,7 @@ namespace Mono.CSharp { IsConstructor = is_constructor; CurrentBlock = null; CurrentFile = 0; + current_phase = Phase.Created; if (parent != null){ // Can only be null for the ResolveType contexts. @@ -434,6 +480,12 @@ namespace Mono.CSharp { } } + public bool HaveCaptureInfo { + get { + return capture_context != null; + } + } + // // Starts a new code branching. This inherits the state of all local // variables and parameters from the current branching. @@ -460,6 +512,14 @@ namespace Mono.CSharp { return current_flow_branching; } + public FlowBranchingException StartFlowBranching (ExceptionStatement stmt) + { + FlowBranchingException branching = new FlowBranchingException ( + CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + // // Ends a code branching. Merges the state of locals and parameters // from all the children of the ending branching. @@ -492,30 +552,141 @@ namespace Mono.CSharp { current_flow_branching = current_flow_branching.Parent; } - public void EmitTopBlock (Block block, InternalParameters ip, Location loc) + public void CaptureVariable (LocalInfo li) + { + capture_context.AddLocal (CurrentAnonymousMethod, li); + li.IsCaptured = true; + } + + public void CaptureParameter (string name, Type t, int idx) + { + + capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx); + } + + // + // Use to register a field as captured + // + public void CaptureField (FieldExpr fe) + { + capture_context.AddField (fe); + } + + // + // Whether anonymous methods have captured variables + // + public bool HaveCapturedVariables () + { + if (capture_context != null) + return capture_context.HaveCapturedVariables; + return false; + } + + // + // Whether anonymous methods have captured fields or this. + // + public bool HaveCapturedFields () + { + if (capture_context != null) + return capture_context.HaveCapturedFields; + return false; + } + + // + // Emits the instance pointer for the host method + // + public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am) + { + if (capture_context != null) + capture_context.EmitMethodHostInstance (target, am); + else if (IsStatic) + target.ig.Emit (OpCodes.Ldnull); + else + target.ig.Emit (OpCodes.Ldarg_0); + } + + // + // Returns whether the `local' variable has been captured by an anonymous + // method + // + public bool IsCaptured (LocalInfo local) + { + return capture_context.IsCaptured (local); + } + + public bool IsParameterCaptured (string name) + { + if (capture_context != null) + return capture_context.IsParameterCaptured (name); + return false; + } + + public void EmitMeta (ToplevelBlock b, InternalParameters ip) + { + if (capture_context != null) + capture_context.EmitHelperClasses (this); + b.EmitMeta (this); + + if (HasReturnLabel) + ReturnLabel = ig.DefineLabel (); + } + + // + // Here until we can fix the problem with Mono.CSharp.Switch, which + // currently can not cope with ig == null during resolve (which must + // be fixed for switch statements to work on anonymous methods). + // + public void EmitTopBlock (ToplevelBlock block, InternalParameters ip, Location loc) + { + if (block == null) + return; + + bool unreachable; + + if (ResolveTopBlock (null, block, ip, loc, out unreachable)){ + EmitMeta (block, ip); + + current_phase = Phase.Emitting; + EmitResolvedTopBlock (block, unreachable); + } + } + + public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block, + InternalParameters ip, Location loc, out bool unreachable) { - bool unreachable = false; + current_phase = Phase.Resolving; + + unreachable = false; + + capture_context = block.CaptureContext; if (!Location.IsNull (loc)) CurrentFile = loc.File; - if (block != null){ +#if PRODUCTION try { +#endif int errors = Report.Errors; - block.EmitMeta (this, ip); + block.ResolveMeta (block, this, ip); + if (Report.Errors == errors){ bool old_do_flow_analysis = DoFlowAnalysis; DoFlowAnalysis = true; + if (anonymous_method_host != null) + current_flow_branching = FlowBranching.CreateBranching ( + anonymous_method_host.CurrentBranching, FlowBranching.BranchingType.Block, + block, loc); + else current_flow_branching = FlowBranching.CreateBranching ( null, FlowBranching.BranchingType.Block, block, loc); if (!block.Resolve (this)) { current_flow_branching = null; DoFlowAnalysis = old_do_flow_analysis; - return; + return false; } FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock (); @@ -523,14 +694,12 @@ namespace Mono.CSharp { DoFlowAnalysis = old_do_flow_analysis; - block.Emit (this); - if (reachability.AlwaysReturns || reachability.AlwaysThrows || reachability.IsUnreachable) unreachable = true; } -#if FIXME +#if PRODUCTION } catch (Exception e) { Console.WriteLine ("Exception caught by the compiler while compiling:"); Console.WriteLine (" Block that caused the problem begin at: " + loc); @@ -540,24 +709,35 @@ namespace Mono.CSharp { CurrentBlock.StartLocation, CurrentBlock.EndLocation); } Console.WriteLine (e.GetType ().FullName + ": " + e.Message); - Console.WriteLine (Report.FriendlyStackTrace (e)); - - Environment.Exit (1); -#else - } finally { -#endif - } + throw; } +#endif if (ReturnType != null && !unreachable){ if (!InIterator){ + if (CurrentAnonymousMethod != null){ + Report.Error (1643, loc, "Not all code paths return a value in anonymous method of type `{0}'", + CurrentAnonymousMethod.Type); + } else { Report.Error (161, loc, "Not all code paths return a value"); - return; + } + + return false; } } + block.CompleteContexts (); + + return true; + } + + public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable) + { + if (block != null) + block.Emit (this); if (HasReturnLabel) ig.MarkLabel (ReturnLabel); + if (return_value != null){ ig.Emit (OpCodes.Ldloc, return_value); ig.Emit (OpCodes.Ret); @@ -583,6 +763,12 @@ namespace Mono.CSharp { ig.Emit (OpCodes.Ret); } } + + // + // Close pending helper classes if we are the toplevel + // + if (capture_context != null && capture_context.ParentToplevel == null) + capture_context.CloseHelperClasses (); } /// @@ -597,7 +783,15 @@ namespace Mono.CSharp { if (check_file && (CurrentFile != loc.File)) return; - ig.MarkSequencePoint (null, loc.Row, 0, 0, 0); + CodeGen.SymbolWriter.MarkSequencePoint (ig, loc.Row, 0); + } + + public void DefineLocalVariable (string name, LocalBuilder builder) + { + if (CodeGen.SymbolWriter == null) + return; + + CodeGen.SymbolWriter.DefineLocalVariable (name, builder); } /// @@ -681,66 +875,65 @@ namespace Mono.CSharp { /// return value from the function. By default this is not /// used. This is only required when returns are found inside /// Try or Catch statements. + /// + /// This method is typically invoked from the Emit phase, so + /// we allow the creation of a return label if it was not + /// requested during the resolution phase. Could be cleaned + /// up, but it would replicate a lot of logic in the Emit phase + /// of the code that uses it. /// public LocalBuilder TemporaryReturn () { if (return_value == null){ return_value = ig.DeclareLocal (ReturnType); + if (!HasReturnLabel){ ReturnLabel = ig.DefineLabel (); HasReturnLabel = true; } + } return return_value; } + /// + /// This method is used during the Resolution phase to flag the + /// need to define the ReturnLabel + /// public void NeedReturnLabel () { - if (!HasReturnLabel) { - ReturnLabel = ig.DefineLabel (); + if (current_phase != Phase.Resolving){ + // + // The reason is that the `ReturnLabel' is declared between + // resolution and emission + // + throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve"); + } + + if (!InIterator && !HasReturnLabel) HasReturnLabel = true; } - } // // Creates a field `name' with the type `t' on the proxy class // public FieldBuilder MapVariable (string name, Type t) { - if (InIterator){ - return IteratorHandler.Current.MapVariable ("v_", name, t); - } + if (InIterator) + return CurrentIterator.MapVariable ("v_", name, t); throw new Exception ("MapVariable for an unknown state"); } - // - // Invoke this routine to remap a VariableInfo into the - // proper MemberAccess expression - // - public Expression RemapLocal (LocalInfo local_info) - { - FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc); - fe.InstanceExpression = new ProxyInstance (); - return fe.DoResolve (this); - } - - public Expression RemapLocalLValue (LocalInfo local_info, Expression right_side) - { - FieldExpr fe = new FieldExpr (local_info.FieldBuilder, loc); - fe.InstanceExpression = new ProxyInstance (); - return fe.DoResolveLValue (this, right_side); - } - public Expression RemapParameter (int idx) { - FieldExpr fe = new FieldExprNoAddress (IteratorHandler.Current.parameter_fields [idx], loc); + FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc); fe.InstanceExpression = new ProxyInstance (); return fe.DoResolve (this); } public Expression RemapParameterLValue (int idx, Expression right_side) { - FieldExpr fe = new FieldExprNoAddress (IteratorHandler.Current.parameter_fields [idx], loc); + FieldExpr fe = new FieldExprNoAddress (CurrentIterator.parameter_fields [idx].FieldBuilder, loc); fe.InstanceExpression = new ProxyInstance (); return fe.DoResolveLValue (this, right_side); } @@ -751,17 +944,59 @@ namespace Mono.CSharp { // public void EmitThis () { + ig.Emit (OpCodes.Ldarg_0); if (InIterator){ - ig.Emit (OpCodes.Ldarg_0); if (!IsStatic){ - FieldBuilder this_field = IteratorHandler.Current.this_field; - if (TypeManager.IsValueType (this_field.FieldType)) - ig.Emit (OpCodes.Ldflda, this_field); - else - ig.Emit (OpCodes.Ldfld, this_field); - } - } else + FieldBuilder this_field = CurrentIterator.this_field.FieldBuilder; + if (TypeManager.IsValueType (this_field.FieldType)) + ig.Emit (OpCodes.Ldflda, this_field); + else + ig.Emit (OpCodes.Ldfld, this_field); + } + } else if (capture_context != null && CurrentAnonymousMethod != null){ + ScopeInfo si = CurrentAnonymousMethod.Scope; + while (si != null){ + if (si.ParentLink != null) + ig.Emit (OpCodes.Ldfld, si.ParentLink); + if (si.THIS != null){ + ig.Emit (OpCodes.Ldfld, si.THIS); + break; + } + si = si.ParentScope; + } + } + } + + // + // Emits the code necessary to load the instance required + // to access the captured LocalInfo + // + public void EmitCapturedVariableInstance (LocalInfo li) + { + if (RemapToProxy){ ig.Emit (OpCodes.Ldarg_0); + return; + } + + if (capture_context == null) + throw new Exception ("Calling EmitCapturedContext when there is no capture_context"); + + capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod); + } + + public void EmitParameter (string name) + { + capture_context.EmitParameter (this, name); + } + + public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load) + { + capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load); + } + + public void EmitAddressOfParameter (string name) + { + capture_context.EmitAddressOfParameter (this, name); } public Expression GetThis (Location loc) @@ -781,8 +1016,6 @@ namespace Mono.CSharp { public abstract class CommonAssemblyModulClass: Attributable { - static string[] attribute_targets = new string [] { "assembly", "module" }; - protected CommonAssemblyModulClass (): base (null) { @@ -795,7 +1028,6 @@ namespace Mono.CSharp { return; } OptAttributes.AddAttributes (attrs); - OptAttributes.CheckTargets (ValidAttributeTargets); } public virtual void Emit (TypeContainer tc) @@ -812,19 +1044,17 @@ namespace Mono.CSharp { if (OptAttributes == null) return null; - EmitContext temp_ec = new EmitContext (new TypeContainer (), Mono.CSharp.Location.Null, null, null, 0, false); + // Ensure that we only have GlobalAttributes, since the Search below isn't safe with other types. + if (!OptAttributes.CheckTargets (this)) + return null; + + EmitContext temp_ec = new EmitContext (RootContext.Tree.Types, Mono.CSharp.Location.Null, null, null, 0, false); Attribute a = OptAttributes.Search (TypeManager.cls_compliant_attribute_type, temp_ec); if (a != null) { a.Resolve (temp_ec); } return a; } - - protected override string[] ValidAttributeTargets { - get { - return attribute_targets; - } - } } public class AssemblyClass: CommonAssemblyModulClass { @@ -832,6 +1062,11 @@ namespace Mono.CSharp { public AssemblyBuilder Builder; bool is_cls_compliant; + public Attribute ClsCompliantAttribute; + + ListDictionary declarative_security; + + static string[] attribute_targets = new string [] { "assembly" }; public AssemblyClass (): base () { @@ -857,19 +1092,53 @@ namespace Mono.CSharp { public void ResolveClsCompliance () { - Attribute a = GetClsCompliantAttribute (); - if (a == null) + ClsCompliantAttribute = GetClsCompliantAttribute (); + if (ClsCompliantAttribute == null) return; - is_cls_compliant = a.GetClsCompliantAttributeValue (null); + is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue (null); } + // fix bug #56621 + private void SetPublicKey (AssemblyName an, byte[] strongNameBlob) + { + try { + // check for possible ECMA key + if (strongNameBlob.Length == 16) { + // will be rejected if not "the" ECMA key + an.SetPublicKey (strongNameBlob); + } + else { + // take it, with or without, a private key + RSA rsa = CryptoConvert.FromCapiKeyBlob (strongNameBlob); + // and make sure we only feed the public part to Sys.Ref + byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa); + + // AssemblyName.SetPublicKey requires an additional header + byte[] publicKeyHeader = new byte [12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 }; + + byte[] encodedPublicKey = new byte [12 + publickey.Length]; + Buffer.BlockCopy (publicKeyHeader, 0, encodedPublicKey, 0, 12); + Buffer.BlockCopy (publickey, 0, encodedPublicKey, 12, publickey.Length); + an.SetPublicKey (encodedPublicKey); + } + } + catch (Exception) { + Report.Error (1548, "Could not strongname the assembly. File `" + + RootContext.StrongNameKeyFile + "' incorrectly encoded."); + Environment.Exit (1); + } + } + + // TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way. public AssemblyName GetAssemblyName (string name, string output) { if (OptAttributes != null) { foreach (Attribute a in OptAttributes.Attrs) { - if (a.Target != "assembly") - continue; + // cannot rely on any resolve-based members before you call Resolve + if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly") + continue; + // TODO: This code is buggy: comparing Attribute name without resolving it is wrong. // However, this is invoked by CodeGen.Init, at which time none of the namespaces // are loaded yet. @@ -878,8 +1147,8 @@ namespace Mono.CSharp { case "AssemblyKeyFileAttribute": case "System.Reflection.AssemblyKeyFileAttribute": if (RootContext.StrongNameKeyFile != null) { - Report.Warning (1616, "Compiler option -keyfile overrides " + - "AssemblyKeyFileAttribute"); + Report.SymbolRelatedToPreviousError (a.Location, a.Name); + Report.Warning (1616, "Compiler option '{0}' overrides '{1}' given in source", "keyfile", "System.Reflection.AssemblyKeyFileAttribute"); } else { string value = a.GetString (); @@ -891,8 +1160,8 @@ namespace Mono.CSharp { case "AssemblyKeyNameAttribute": case "System.Reflection.AssemblyKeyNameAttribute": if (RootContext.StrongNameKeyContainer != null) { - Report.Warning (1616, "Compiler option -keycontainer overrides " + - "AssemblyKeyNameAttribute"); + Report.SymbolRelatedToPreviousError (a.Location, a.Name); + Report.Warning (1616, "keycontainer", "Compiler option '{0}' overrides '{1}' given in source", "System.Reflection.AssemblyKeyNameAttribute"); } else { string value = a.GetString (); @@ -944,25 +1213,7 @@ namespace Mono.CSharp { if (RootContext.StrongNameDelaySign) { // delayed signing - DO NOT include private key - try { - // check for possible ECMA key - if (snkeypair.Length == 16) { - // will be rejected if not "the" ECMA key - an.KeyPair = new StrongNameKeyPair (snkeypair); - } - else { - // take it, with or without, a private key - RSA rsa = CryptoConvert.FromCapiKeyBlob (snkeypair); - // and make sure we only feed the public part to Sys.Ref - byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa); - an.KeyPair = new StrongNameKeyPair (publickey); - } - } - catch (Exception) { - Report.Error (1548, "Could not strongname the assembly. File `" + - RootContext.StrongNameKeyFile + "' incorrectly encoded."); - Environment.Exit (1); - } + SetPublicKey (an, snkeypair); } else { // no delay so we make sure we have the private key @@ -996,8 +1247,52 @@ namespace Mono.CSharp { public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder) { + if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (true)) { + if (declarative_security == null) + declarative_security = new ListDictionary (); + + a.ExtractSecurityPermissionSet (declarative_security); + return; + } + Builder.SetCustomAttribute (customBuilder); } + + public override void Emit (TypeContainer tc) + { + base.Emit (tc); + + if (declarative_security != null) { + + MethodInfo add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic); + object builder_instance = Builder; + + try { + // Microsoft runtime hacking + if (add_permission == null) { + Type assembly_builder = typeof (AssemblyBuilder).Assembly.GetType ("System.Reflection.Emit.AssemblyBuilderData"); + add_permission = assembly_builder.GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic); + + FieldInfo fi = typeof (AssemblyBuilder).GetField ("m_assemblyData", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); + builder_instance = fi.GetValue (Builder); + } + + object[] args = new object [] { declarative_security [SecurityAction.RequestMinimum], + declarative_security [SecurityAction.RequestOptional], + declarative_security [SecurityAction.RequestRefuse] }; + add_permission.Invoke (builder_instance, args); + } + catch { + Report.RuntimeMissingSupport (Location.Null, "assembly permission setting"); + } + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } } public class ModuleClass: CommonAssemblyModulClass { @@ -1005,6 +1300,8 @@ namespace Mono.CSharp { public ModuleBuilder Builder; bool m_module_is_unsafe; + static string[] attribute_targets = new string [] { "module" }; + public ModuleClass (bool is_unsafe) { m_module_is_unsafe = is_unsafe; @@ -1033,18 +1330,29 @@ namespace Mono.CSharp { return; } - ApplyAttributeBuilder (null, new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0])); + Builder.SetCustomAttribute (new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0])); } public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder) { - if (a != null && a.Type == TypeManager.cls_compliant_attribute_type) { - Report.Warning_T (3012, a.Location); - return; + if (a.Type == TypeManager.cls_compliant_attribute_type) { + if (CodeGen.Assembly.ClsCompliantAttribute == null) { + Report.Warning (3012, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking"); + } + else if (CodeGen.Assembly.IsClsCompliant != a.GetBoolean ()) { + Report.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.Name); + Report.Error (3017, a.Location, "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly"); + return; + } } Builder.SetCustomAttribute (customBuilder); } - } + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } }