// (C) 2001, 2002, 2003 Ximian, Inc.
// (C) 2004 Novell, Inc.
//
-//#define PRODUCTION
+
+#if !DEBUG
+ #define PRODUCTION
+#endif
+
using System;
using System.IO;
using System.Collections;
//
if (SymbolWriter == null) {
Report.Warning (
- -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.");
+ -18, 1, "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;
}
}
if (an.KeyPair != null) {
// If we are going to strong name our assembly make
// sure all its refs are strong named
- foreach (Assembly a in TypeManager.GetAssemblies ()) {
+ foreach (Assembly a in RootNamespace.Global.Assemblies) {
AssemblyName ref_name = a.GetName ();
byte [] b = ref_name.GetPublicKeyToken ();
if (b == null || b.Length == 0) {
- Report.Warning (1577, "Assembly generation failed " +
+ Report.Error (1577, "Assembly generation failed " +
"-- Referenced assembly '" +
ref_name.Name +
"' does not have a strong name.");
}
}
- //
- // Provides "local" store across code that can yield: locals
- // or fields, notice that this should not be used by anonymous
- // methods to create local storage, those only require
- // variable mapping.
- //
- public class VariableStorage {
- FieldBuilder fb;
- LocalBuilder local;
-
- static int count;
-
- public VariableStorage (EmitContext ec, Type t)
- {
- count++;
- if (ec.InIterator)
- fb = ec.CurrentIterator.MapVariable ("s_", count.ToString (), t);
- else
- local = ec.ig.DeclareLocal (t);
- }
-
- public void EmitThis (ILGenerator ig)
- {
- if (fb != null)
- ig.Emit (OpCodes.Ldarg_0);
- }
-
- public void EmitStore (ILGenerator ig)
- {
- if (fb == null)
- ig.Emit (OpCodes.Stloc, local);
- else
- ig.Emit (OpCodes.Stfld, fb);
- }
-
- 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 (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 (ig);
- if (fb == null) {
- value_type_call = local.LocalType.IsValueType;
-
- if (value_type_call)
- ig.Emit (OpCodes.Ldloca, local);
- else
- ig.Emit (OpCodes.Ldloc, local);
- } else {
- value_type_call = fb.FieldType.IsValueType;
-
- if (value_type_call)
- ig.Emit (OpCodes.Ldflda, fb);
- else
- ig.Emit (OpCodes.Ldfld, fb);
- }
-
- ig.Emit (value_type_call ? OpCodes.Call : OpCodes.Callvirt, mi);
- }
- }
-
/// <summary>
/// An Emit Context is created for each body of code (from methods,
/// properties bodies, indexer bodies or constructor bodies)
/// </summary>
public class EmitContext {
- public DeclSpace DeclSpace;
+ public readonly DeclSpace DeclSpace;
public DeclSpace TypeContainer;
public ILGenerator ig;
/// Whether we're control flow analysis enabled
/// </summary>
public bool DoFlowAnalysis;
-
+
+ /// <summary>
+ /// Whether we're control flow analysis disabled on struct
+ /// </summary>
+ public bool OmitStructFlowAnalysis;
+
/// <summary>
/// Keeps track of the Type to LocalBuilder temporary storage created
/// to store structures (used to compute the address of the structure
public bool IsLastStatement;
- /// <summary>
- /// Whether remapping of locals, parameters and fields is turned on.
- /// Used by iterators and anonymous methods.
- /// </summary>
- public bool RemapToProxy;
-
/// <summary>
/// Whether we are inside an unsafe block
/// </summary>
/// </summary>
public bool InFixedInitializer;
+ public bool InRefOutArgumentResolving;
+
+ public bool InCatch;
+ public bool InFinally;
+
/// <summary>
/// Whether we are inside an anonymous method.
/// </summary>
- public AnonymousMethod CurrentAnonymousMethod;
+ public AnonymousContainer CurrentAnonymousMethod;
/// <summary>
/// Location for this EmitContext
Phase current_phase;
FlowBranching current_flow_branching;
+
+ static int next_id = 0;
+ int id = ++next_id;
+
+ public override string ToString ()
+ {
+ return String.Format ("EmitContext ({0}:{1}:{2})", id,
+ CurrentIterator, capture_context, loc);
+ }
public EmitContext (DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
Type return_type, int code_flags, bool is_constructor)
IsStatic = (code_flags & Modifiers.STATIC) != 0;
MethodIsStatic = IsStatic;
InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0;
- RemapToProxy = InIterator;
ReturnType = return_type;
IsConstructor = is_constructor;
CurrentBlock = null;
{
FlowBranching.BranchingType type;
- if (CurrentBranching.Type == FlowBranching.BranchingType.Switch)
+ if ((CurrentBranching != null) &&
+ (CurrentBranching.Type == FlowBranching.BranchingType.Switch))
type = FlowBranching.BranchingType.SwitchSection;
else
type = FlowBranching.BranchingType.Block;
- current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, block, block.StartLocation);
+ DoFlowAnalysis = true;
+
+ current_flow_branching = FlowBranching.CreateBranching (
+ CurrentBranching, type, block, block.StartLocation);
return current_flow_branching;
}
public void CaptureThis ()
{
- capture_context.CaptureThis ();
+ capture_context.CaptureThis (CurrentAnonymousMethod);
}
//
public void CaptureField (FieldExpr fe)
{
- capture_context.AddField (fe);
+ capture_context.AddField (this, CurrentAnonymousMethod, fe);
}
//
return false;
}
- public void EmitMeta (ToplevelBlock b, InternalParameters ip)
+ public void EmitMeta (ToplevelBlock b)
{
if (capture_context != null)
capture_context.EmitAnonymousHelperClasses (this);
// 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)
+ public void EmitTopBlock (IMethodData md, ToplevelBlock block)
{
if (block == null)
return;
bool unreachable;
- if (ResolveTopBlock (null, block, ip, loc, out unreachable)){
- EmitMeta (block, ip);
+ if (ResolveTopBlock (null, block, md.ParameterInfo, md, out unreachable)){
+ EmitMeta (block);
current_phase = Phase.Emitting;
EmitResolvedTopBlock (block, unreachable);
}
}
+ bool resolved;
+
public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,
- InternalParameters ip, Location loc, out bool unreachable)
+ Parameters ip, IMethodData md, out bool unreachable)
{
current_phase = Phase.Resolving;
unreachable = false;
+ if (resolved)
+ return true;
+
capture_context = block.CaptureContext;
- if (!Location.IsNull (loc))
+ if (!loc.IsNull)
CurrentFile = loc.File;
#if PRODUCTION
try {
#endif
- int errors = Report.Errors;
-
- block.ResolveMeta (block, this, ip);
- if (Report.Errors != errors)
+ if (!block.ResolveMeta (this, ip))
return false;
- 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 false;
- }
+ bool old_do_flow_analysis = DoFlowAnalysis;
+ DoFlowAnalysis = true;
- FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
+ if (anonymous_method_host != null)
+ current_flow_branching = FlowBranching.CreateBranching (
+ anonymous_method_host.CurrentBranching,
+ FlowBranching.BranchingType.Block, block, loc);
+ else
+ current_flow_branching = block.TopLevelBranching;
+
+ if (!block.Resolve (this)) {
current_flow_branching = null;
-
DoFlowAnalysis = old_do_flow_analysis;
+ return false;
+ }
+
+ FlowBranching.Reachability reachability = current_flow_branching.MergeTopBlock ();
+ current_flow_branching = null;
- if (reachability.AlwaysReturns ||
- reachability.AlwaysThrows ||
- reachability.IsUnreachable)
- unreachable = true;
+ DoFlowAnalysis = old_do_flow_analysis;
+
+ if (reachability.AlwaysReturns ||
+ reachability.AlwaysThrows ||
+ reachability.IsUnreachable)
+ unreachable = true;
#if PRODUCTION
} catch (Exception e) {
Console.WriteLine ("Exception caught by the compiler while compiling:");
}
#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");
- }
-
+ if (ReturnType != null && !unreachable) {
+ if (CurrentAnonymousMethod == null) {
+ Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
+ return false;
+ } else if (!CurrentAnonymousMethod.IsIterator) {
+ Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
+ CurrentAnonymousMethod.GetSignatureForError ());
return false;
}
}
- block.CompleteContexts ();
+ block.CompleteContexts ();
+ resolved = true;
return true;
}
// this case.
//
+ bool in_iterator = (CurrentAnonymousMethod != null) &&
+ CurrentAnonymousMethod.IsIterator && InIterator;
+
if ((block != null) && block.IsDestructor) {
// Nothing to do; S.R.E automatically emits a leave.
- } else if (HasReturnLabel || (!unreachable && !InIterator)) {
+ } else if (HasReturnLabel || (!unreachable && !in_iterator)) {
if (ReturnType != null)
ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
ig.Emit (OpCodes.Ret);
/// </summary>
public void Mark (Location loc, bool check_file)
{
- if ((CodeGen.SymbolWriter == null) || Location.IsNull (loc))
+ if ((CodeGen.SymbolWriter == null) || loc.IsNull)
return;
if (check_file && (CurrentFile != loc.File))
return;
- CodeGen.SymbolWriter.MarkSequencePoint (ig, loc.Row, 0);
+ CodeGen.SymbolWriter.MarkSequencePoint (ig, loc.Row, loc.Column);
}
public void DefineLocalVariable (string name, LocalBuilder builder)
HasReturnLabel = true;
}
- //
- // Creates a field `name' with the type `t' on the proxy class
- //
- public FieldBuilder MapVariable (string name, Type t)
- {
- if (InIterator)
- return CurrentIterator.MapVariable ("v_", name, t);
-
- throw new Exception ("MapVariable for an unknown state");
- }
-
- public Expression RemapParameter (int idx)
- {
- 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 (CurrentIterator.parameter_fields [idx].FieldBuilder, loc);
- fe.InstanceExpression = new ProxyInstance ();
- return fe.DoResolveLValue (this, right_side);
- }
-
//
// Emits the proper object to address fields on a remapped
// variable/parameter to field in anonymous-method/iterator proxy classes.
public void EmitThis ()
{
ig.Emit (OpCodes.Ldarg_0);
- if (InIterator){
- if (!IsStatic){
- 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){
+ if (capture_context != null && CurrentAnonymousMethod != null){
ScopeInfo si = CurrentAnonymousMethod.Scope;
while (si != null){
if (si.ParentLink != null)
//
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");
}
- public abstract class CommonAssemblyModulClass: Attributable {
+ public abstract class CommonAssemblyModulClass : Attributable {
protected CommonAssemblyModulClass ():
base (null)
{
OptAttributes.Emit (ec, this);
}
- protected Attribute GetClsCompliantAttribute ()
+ protected Attribute ResolveAttribute (Type a_type)
{
if (OptAttributes == null)
return null;
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);
+ Attribute a = OptAttributes.Search (a_type, temp_ec);
if (a != null) {
a.Resolve (temp_ec);
}
}
}
- public class AssemblyClass: CommonAssemblyModulClass {
+ public class AssemblyClass : CommonAssemblyModulClass {
// TODO: make it private and move all builder based methods here
public AssemblyBuilder Builder;
bool is_cls_compliant;
+ bool wrap_non_exception_throws;
+
public Attribute ClsCompliantAttribute;
ListDictionary declarative_security;
- static string[] attribute_targets = new string [] { "assembly" };
+ // Module is here just because of error messages
+ static string[] attribute_targets = new string [] { "assembly", "module" };
public AssemblyClass (): base ()
{
- is_cls_compliant = false;
+ wrap_non_exception_throws = true;
}
public bool IsClsCompliant {
}
}
+ public bool WrapNonExceptionThrows {
+ get {
+ return wrap_non_exception_throws;
+ }
+ }
+
public override AttributeTargets AttributeTargets {
get {
return AttributeTargets.Assembly;
}
}
- public override bool IsClsCompliaceRequired(DeclSpace ds)
+ public override bool IsClsComplianceRequired(DeclSpace ds)
{
return is_cls_compliant;
}
- public void ResolveClsCompliance ()
+ public void Resolve ()
{
- ClsCompliantAttribute = GetClsCompliantAttribute ();
- if (ClsCompliantAttribute == null)
- return;
+ ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
+ if (ClsCompliantAttribute != null) {
+ is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue (null);
+ }
- is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue (null);
+#if NET_2_0
+ Attribute a = ResolveAttribute (TypeManager.runtime_compatibility_attr_type);
+ if (a != null) {
+ object val = a.GetPropertyValue ("WrapNonExceptionThrows");
+ if (val != null)
+ wrap_non_exception_throws = (bool)val;
+ }
+#endif
}
// fix bug #56621
}
}
catch (Exception) {
- Report.Error (1548, "Could not strongname the assembly. File `" +
- RootContext.StrongNameKeyFile + "' incorrectly encoded.");
+ Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' is incorrectly encoded");
Environment.Exit (1);
}
}
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
+ // TODO: This code is buggy: comparing Attribute name without resolving is wrong.
+ // However, this is invoked by CodeGen.Init, when none of the namespaces
// are loaded yet.
+ // TODO: Does not handle quoted attributes properly
switch (a.Name) {
case "AssemblyKeyFile":
case "AssemblyKeyFileAttribute":
case "System.Reflection.AssemblyKeyFileAttribute":
if (RootContext.StrongNameKeyFile != null) {
Report.SymbolRelatedToPreviousError (a.Location, a.Name);
- Report.Warning (1616, "Compiler option '{0}' overrides '{1}' given in source", "keyfile", "System.Reflection.AssemblyKeyFileAttribute");
+ Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
+ "keyfile", "System.Reflection.AssemblyKeyFileAttribute");
}
else {
string value = a.GetString ();
case "System.Reflection.AssemblyKeyNameAttribute":
if (RootContext.StrongNameKeyContainer != null) {
Report.SymbolRelatedToPreviousError (a.Location, a.Name);
- Report.Warning (1616, "keycontainer", "Compiler option '{0}' overrides '{1}' given in source", "System.Reflection.AssemblyKeyNameAttribute");
+ Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
+ "keycontainer", "System.Reflection.AssemblyKeyNameAttribute");
}
else {
string value = a.GetString ();
catch (CryptographicException) {
if (snkeypair.Length == 16) {
// error # is different for ECMA key
- Report.Error (1606, "Could not strongname the assembly. " +
+ Report.Error (1606, "Could not sign the assembly. " +
"ECMA key can only be used to delay-sign assemblies");
}
else {
- Report.Error (1548, "Could not strongname the assembly. File `" +
- RootContext.StrongNameKeyFile +
- "' doesn't have a private key.");
+ Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' does not have a private key");
}
return null;
}
}
}
else {
- Report.Error (1548, "Could not strongname the assembly. File `" +
- RootContext.StrongNameKeyFile + "' not found.");
+ Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' does not exist");
return null;
}
return an;
}
+ void Error_AssemblySigning (string text)
+ {
+ Report.Error (1548, "Error during assembly signing. " + text);
+ }
+
public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
{
if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (true)) {
return;
}
+ if (a.Type == TypeManager.assembly_culture_attribute_type) {
+ string value = a.GetString ();
+ if (value == null || value.Length == 0)
+ return;
+
+ if (RootContext.Target == Target.Exe) {
+ a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty");
+ return;
+ }
+ }
+
Builder.SetCustomAttribute (customBuilder);
}
Report.RuntimeMissingSupport (Location.Null, "assembly permission setting");
}
}
+
+#if NET_2_0
+ if (!OptAttributes.Contains (TypeManager.runtime_compatibility_attr_type, null)) {
+ ConstructorInfo ci = TypeManager.runtime_compatibility_attr_type.GetConstructor (TypeManager.NoTypes);
+ PropertyInfo pi = TypeManager.runtime_compatibility_attr_type.GetProperty ("WrapNonExceptionThrows");
+ Builder.SetCustomAttribute (new CustomAttributeBuilder (ci, new object [0],
+ new PropertyInfo [] { pi }, new object[] { true } ));
+ }
+#endif
}
public override string[] ValidAttributeTargets {
}
}
- public class ModuleClass: CommonAssemblyModulClass {
+ public class ModuleClass : CommonAssemblyModulClass {
// TODO: make it private and move all builder based methods here
public ModuleBuilder Builder;
bool m_module_is_unsafe;
+ public CharSet DefaultCharSet = CharSet.Ansi;
+ public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
+
static string[] attribute_targets = new string [] { "module" };
public ModuleClass (bool is_unsafe)
}
}
- public override bool IsClsCompliaceRequired(DeclSpace ds)
+ public override bool IsClsComplianceRequired(DeclSpace ds)
{
return CodeGen.Assembly.IsClsCompliant;
}
{
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");
+ Report.Warning (3012, 1, 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.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.GetSignatureForError ());
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);
}
+ /// <summary>
+ /// It is called very early therefore can resolve only predefined attributes
+ /// </summary>
+ public void ResolveAttributes ()
+ {
+#if NET_2_0
+ Attribute a = ResolveAttribute (TypeManager.default_charset_type);
+ if (a != null) {
+ DefaultCharSet = a.GetCharSetValue ();
+ switch (DefaultCharSet) {
+ case CharSet.Ansi:
+ case CharSet.None:
+ break;
+ case CharSet.Auto:
+ DefaultCharSetType = TypeAttributes.AutoClass;
+ break;
+ case CharSet.Unicode:
+ DefaultCharSetType = TypeAttributes.UnicodeClass;
+ break;
+ default:
+ Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
+ break;
+ }
+ }
+#endif
+ }
+
public override string[] ValidAttributeTargets {
get {
return attribute_targets;