using System.Reflection;
using System.Runtime.CompilerServices;
-[assembly: AssemblyVersion("0.94")]
+[assembly: AssemblyVersion("0.95")]
[assembly: AssemblyTitle ("Mono C# Compiler")]
[assembly: AssemblyDescription ("Mono C# Compiler with Generics")]
[assembly: AssemblyCopyright ("2001, 2002, 2003 Ximian, Inc.")]
// attribute.cs: Attribute Handler
//
// Author: Ravi Pratap (ravi@ximian.com)
+// Marek Safar (marek.safar@seznam.cz)
//
// Licensed under the terms of the GNU GPL
//
return sc.Value;
}
+ /// <summary>
+ /// Returns condition of ConditionalAttribute
+ /// </summary>
+ public string GetConditionalAttributeValue (DeclSpace ds)
+ {
+ if (pos_values == null) {
+ EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
+
+ // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
+ // But because a lot of attribute class code must be rewritten will be better to wait...
+ Resolve (ec);
+ }
+
+ // Some error occurred
+ if (pos_values [0] == null)
+ return null;
+
+ return (string)pos_values [0];
+ }
+
/// <summary>
/// Creates the instance of ObsoleteAttribute from this attribute instance
/// </summary>
return Search (t, ec, true);
}
+ /// <summary>
+ /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
+ /// </summary>
+ public Attribute[] SearchMulti (Type t, EmitContext ec)
+ {
+ ArrayList ar = null;
+
+ foreach (Attribute a in Attrs) {
+ if (a.ResolveType (ec, false) == t) {
+ if (ar == null)
+ ar = new ArrayList ();
+ ar.Add (a);
+ }
+ }
+
+ return ar == null ? null : ar.ToArray (typeof (Attribute)) as Attribute[];
+ }
+
public void Emit (EmitContext ec, Attributable ias)
{
ListDictionary ld = new ListDictionary ();
static PtrHashtable analyzed_types = new PtrHashtable ();
static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
+ static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
private AttributeTester ()
{
}
Report.Warning_T (618, loc, member, oa.Message);
}
+
+ public static bool IsConditionalMethodExcluded (MethodBase mb)
+ {
+ object excluded = analyzed_method_excluded [mb];
+ if (excluded != null)
+ return excluded == TRUE ? true : false;
+
+ ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[];
+ if (attrs.Length == 0) {
+ analyzed_method_excluded.Add (mb, FALSE);
+ return false;
+ }
+
+ foreach (ConditionalAttribute a in attrs) {
+ if (RootContext.AllDefines.Contains (a.ConditionString)) {
+ analyzed_method_excluded.Add (mb, FALSE);
+ return false;
+ }
+ }
+ analyzed_method_excluded.Add (mb, TRUE);
+ return true;
+ }
}
}
//
// Authors: Miguel de Icaza (miguel@gnu.org)
// Martin Baulig (martin@gnome.org)
+// Marek Safar (marek.safar@seznam.cz)
//
// Licensed under the terms of the GNU GPL
//
}
}
-
//
// IMemberContainer
//
public MethodBuilder MethodBuilder;
public MethodData MethodData;
ReturnParameter return_attributes;
- bool should_ignore;
/// <summary>
/// Modifiers allowed in a class declaration
/// <summary>
/// Use this method when MethodBuilder is null
/// </summary>
- public string GetSignatureForError (TypeContainer tc)
+ public override string GetSignatureForError (TypeContainer tc)
{
- System.Text.StringBuilder args = new System.Text.StringBuilder ("");
+ // TODO: move to parameters
+ System.Text.StringBuilder args = new System.Text.StringBuilder ();
if (parameter_info.Parameters.FixedParameters != null) {
for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
- Parameter p = parameter_info.Parameters.FixedParameters [i];
+ Parameter p = parameter_info.Parameters.FixedParameters [i];
args.Append (p.GetSignatureForError ());
if (i < parameter_info.Parameters.FixedParameters.Length - 1)
}
}
- return String.Concat (tc.Name, ".", Name, "(", args.ToString (), ")");
+ return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
}
void DuplicateEntryPoint (MethodInfo b, Location location)
MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
}
- if (a.Type == TypeManager.dllimport_type)
+ if (a.Type == TypeManager.dllimport_type) {
+ const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+ if ((ModFlags & extern_static) != extern_static) {
+ //"The DllImport attribute must be specified on a method marked `static' and `extern'"
+ Report.Error_T (601, a.Location);
+ }
+
return;
+ }
MethodBuilder.SetCustomAttribute (cb);
}
if (!MethodData.Define (container))
return false;
- should_ignore = MethodData.ShouldIgnore ();
-
//
// Setup iterator if we are one
//
return GetObsoleteAttribute (ds);
}
- public bool ShouldIgnore ()
+ /// <summary>
+ /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
+ /// </summary>
+ public bool IsExcluded (EmitContext ec)
{
- return should_ignore;
+ if ((caching_flags & Flags.Excluded_Undetected) == 0)
+ return (caching_flags & Flags.Excluded) != 0;
+
+ caching_flags &= ~Flags.Excluded_Undetected;
+
+ if (parent_method == null) {
+ if (OptAttributes == null)
+ return false;
+
+ Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
+
+ if (attrs == null)
+ return false;
+
+ foreach (Attribute a in attrs) {
+ string condition = a.GetConditionalAttributeValue (ds);
+ if (RootContext.AllDefines.Contains (condition))
+ return false;
+ }
+
+ caching_flags |= Flags.Excluded;
+ return true;
+ }
+
+ IMethodData md = TypeManager.GetMethod (parent_method);
+ if (md == null) {
+ if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
+ caching_flags |= Flags.Excluded;
+ return true;
+ }
+ return false;
+ }
+
+ if (md.IsExcluded (ec)) {
+ caching_flags |= Flags.Excluded;
+ return true;
+ }
+ return false;
}
GenericMethod IMethodData.GenericMethod {
EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
ObsoleteAttribute GetObsoleteAttribute ();
- bool ShouldIgnore ();
+ string GetSignatureForError (TypeContainer tc);
+ bool IsExcluded (EmitContext ec);
}
//
protected bool is_method;
protected Type declaring_type;
- //
- // It can either hold a string with the condition, or an arraylist of conditions.
- object conditionals;
EmitContext ec;
MethodBuilder builder = null;
this.modifiers = modifiers;
this.flags = flags;
this.is_method = is_method;
- this.conditionals = null;
this.method = method;
}
//
// Attributes.
//
- Attribute dllimport_attribute = null;
-
public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
EmitContext ec)
{
if (attr_type == TypeManager.conditional_attribute_type) {
if (!ApplyConditionalAttribute (a))
return false;
- } else if (attr_type == TypeManager.dllimport_type) {
- if (!is_method) {
- Attribute.Error_AttributeNotValidForElement (a, method.Location);
- return false;
- }
- if (!ApplyDllImportAttribute (a))
- return false;
- }
- }
-
- return true;
}
-
- //
- // Applies the `DllImport' attribute to the method.
- //
- protected virtual bool ApplyDllImportAttribute (Attribute a)
- {
- const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
- if ((modifiers & extern_static) != extern_static) {
- Report.Error (601, method.Location,
- "The DllImport attribute must be specified on a method " +
- "marked `static' and `extern'.");
- return false;
}
- flags |= MethodAttributes.PinvokeImpl;
- dllimport_attribute = a;
return true;
}
return false;
}
- //
- // The likelyhood that the conditional will be more than 1 is very slim
- //
- if (conditionals == null)
- conditionals = condition;
- else if (conditionals is string){
- string s = (string) conditionals;
- conditionals = new ArrayList ();
- ((ArrayList)conditionals).Add (s);
- } else
- ((ArrayList)conditionals).Add (condition);
-
return true;
}
- //
- // Checks whether this method should be ignored due to its Conditional attributes.
- //
- public bool ShouldIgnore ()
- {
- // When we're overriding a virtual method, we implicitly inherit the
- // Conditional attributes from our parent.
- if (member.ParentMethod != null) {
- TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
- member.ParentMethod);
-
- if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
- return true;
- }
-
- if (conditionals != null){
- if (conditionals is string){
- if (RootContext.AllDefines [conditionals] == null)
- return true;
- } else {
- foreach (string condition in (ArrayList) conditionals)
- if (RootContext.AllDefines [condition] == null)
- return true;
- }
- }
- return false;
- }
-
public bool Define (TypeContainer container)
{
MethodInfo implementing = null;
IsImplementing = true;
}
- //
- // Create the MethodBuilder for the method
- //
- if ((flags & MethodAttributes.PinvokeImpl) != 0) {
- if ((modifiers & Modifiers.STATIC) == 0) {
- Report.Error (601, method.Location,
- "The DllImport attribute must be specified on " +
- "a method marked 'static' and 'extern'.");
- return false;
- }
- builder = dllimport_attribute.DefinePInvokeMethod (
- ec, container.TypeBuilder, method_name, flags,
- method.ReturnType, ParameterTypes);
- } else if (builder == null)
- builder = container.TypeBuilder.DefineMethod (
- method_name, flags, method.CallingConventions,
- method.ReturnType, ParameterTypes);
- else
- builder.SetGenericMethodSignature (
- flags, method.CallingConventions,
- method.ReturnType, ParameterTypes);
+ DefineMethodBuilder (ec, container, method_name, ParameterTypes);
if (builder == null)
return false;
return true;
}
+ /// <summary>
+ /// Create the MethodBuilder for the method
+ /// </summary>
+ void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
+ {
+ const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+
+ if ((modifiers & extern_static) == extern_static) {
+
+ if (method.OptAttributes != null) {
+ Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
+ if (dllimport_attribute != null) {
+ flags |= MethodAttributes.PinvokeImpl;
+ builder = dllimport_attribute.DefinePInvokeMethod (
+ ec, container.TypeBuilder, method_name, flags,
+ method.ReturnType, ParameterTypes);
+
+ return;
+ }
+ }
+
+ // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
+ // We are more strict than Microsoft and report CS0626 like error
+ if (method.OptAttributes == null ||
+ !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
+ //"Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation"
+ Report.Error_T (626, method.Location, method.GetSignatureForError (container));
+ return;
+ }
+ }
+
+ if (builder == null)
+ builder = container.TypeBuilder.DefineMethod (
+ method_name, flags, method.CallingConventions,
+ method.ReturnType, ParameterTypes);
+ else
+ builder.SetGenericMethodSignature (
+ flags, method.CallingConventions,
+ method.ReturnType, ParameterTypes);
+ }
+
//
// Emits the code
//
return true;
}
+ /// <summary>
+ /// Use this method when MethodBuilder is null
+ /// </summary>
+ public virtual string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (tc.Name, '.', Name);
+ }
+
protected override bool IsIdentifierClsCompliant (DeclSpace ds)
{
return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
return method_data.MethodBuilder;
}
- public override string MethodName {
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (base.GetSignatureForError (tc), ".get");
+ }
+
+ public override string MethodName
+ {
get {
return "get_" + method.ShortName;
}
return method_data.MethodBuilder;
}
+ public override string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (base.GetSignatureForError (tc), ".set");
+ }
+
public override string MethodName {
get {
return "set_" + method.ShortName;
{
method_data.Emit (container, this);
block = null;
+ }
- }
+ public virtual string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (tc.Name, '.', method.Name);
+ }
public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
{
return method.GetObsoleteAttribute (method.ds);
}
- bool IMethodData.ShouldIgnore ()
+ public bool IsExcluded (EmitContext ec)
{
- return method_data.ShouldIgnore ();
+ return false;
}
GenericMethod IMethodData.GenericMethod {
ig.Emit (OpCodes.Ret);
}
+ public string GetSignatureForError (TypeContainer tc)
+ {
+ return String.Concat (tc.Name, '.', method.Name);
+ }
+
protected abstract MethodInfo DelegateMethodInfo { get; }
public Type[] ParameterTypes {
return method.GetObsoleteAttribute (method.ds);
}
- bool IMethodData.ShouldIgnore ()
+ public bool IsExcluded (EmitContext ec)
{
- return method_data.ShouldIgnore ();
+ return false;
}
GenericMethod IMethodData.GenericMethod {
default: return "";
}
}
+
+ public override string GetSignatureForError(TypeContainer tc)
+ {
+ return Prototype (tc);
+ }
public override string ToString ()
{
// decl.cs: Declaration base class for structs, classes, enums and interfaces.
//
// Author: Miguel de Icaza (miguel@gnu.org)
+// Marek Safar (marek.safar@seznam.cz)
//
// Licensed under the terms of the GNU GPL
//
HasCompliantAttribute_Undetected = 1 << 5, // Presence of CLSCompliantAttribute has not been detected
HasClsCompliantAttribute = 1 << 6, // Type has CLSCompliantAttribute
ClsCompliantAttributeTrue = 1 << 7, // Type has CLSCompliant (true)
+ Excluded_Undetected = 1 << 8, // Conditional attribute has not been detected yet
+ Excluded = 1 << 9 // Method is conditional
+
}
/// <summary>
Name = name.GetName (!(this is GenericMethod) && !(this is Method));
MemberName = name;
Location = loc;
- caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected;
+ caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
}
/// <summary>
return null;
}
+
+ private static ArrayList almostMatchedMembers = new ArrayList (4);
+
//
// FIXME: Probably implement a cache for (t,name,current_access_set)?
//
string name, MemberTypes mt,
BindingFlags bf, Location loc)
{
+ almostMatchedMembers.Clear ();
+
MemberInfo [] mi = TypeManager.MemberLookup (
- container_type, qualifier_type,queried_type, mt, bf, name);
+ container_type, qualifier_type,queried_type, mt, bf, name,
+ almostMatchedMembers);
if (mi == null)
return null;
e = MemberLookup (ec, ec.ContainerType, qualifier_type, queried_type,
name, mt, bf, loc);
- if (e != null)
- return e;
-
- // Error has already been reported.
- if (errors < Report.Errors)
- return null;
+ if (e == null && errors == Report.Errors)
+ // No errors were reported by MemberLookup, but there was an error.
+ MemberLookupFailed (ec, qualifier_type, queried_type, name,
+ null, loc);
- MemberLookupFailed (ec, qualifier_type, queried_type, name,
- null, loc);
- return null;
+ return e;
}
public static void MemberLookupFailed (EmitContext ec, Type qualifier_type,
Type queried_type, string name,
string class_name, Location loc)
{
+ if (almostMatchedMembers.Count != 0) {
+ if (qualifier_type == null) {
+ foreach (MemberInfo m in almostMatchedMembers)
+ Report.Error (38, loc,
+ "Cannot access non-static member `{0}' via nested type `{1}'",
+ TypeManager.GetFullNameSignature (m),
+ TypeManager.CSharpName (ec.ContainerType));
+ return;
+ }
+
+
+ if (qualifier_type != ec.ContainerType) {
+ // Although a derived class can access protected members of
+ // its base class it cannot do so through an instance of the
+ // base class (CS1540). If the qualifier_type is a parent of the
+ // ec.ContainerType and the lookup succeeds with the latter one,
+ // then we are in this situation.
+ foreach (MemberInfo m in almostMatchedMembers)
+ Report.Error (1540, loc,
+ "Cannot access protected member `{0}' via a qualifier of type `{1}';"
+ + " the qualifier must be of type `{2}' (or derived from it)",
+ TypeManager.GetFullNameSignature (m),
+ TypeManager.CSharpName (qualifier_type),
+ TypeManager.CSharpName (ec.ContainerType));
+ return;
+ }
+ almostMatchedMembers.Clear ();
+ }
+
MemberInfo[] mi = TypeManager.MemberLookup (queried_type, null, queried_type,
AllMemberTypes, AllBindingFlags |
- BindingFlags.NonPublic, name);
+ BindingFlags.NonPublic, name, null);
if (mi == null) {
if (class_name != null)
if (TypeManager.MemberLookup (queried_type, null, queried_type,
AllMemberTypes, AllBindingFlags |
- BindingFlags.NonPublic, name) == null) {
+ BindingFlags.NonPublic, name, null) == null) {
if ((mi.Length == 1) && (mi [0] is Type)) {
Type t = (Type) mi [0];
}
}
- if ((qualifier_type != null) && (qualifier_type != ec.ContainerType) &&
- ec.ContainerType.IsSubclassOf (qualifier_type)) {
- // Although a derived class can access protected members of
- // its base class it cannot do so through an instance of the
- // base class (CS1540). If the qualifier_type is a parent of the
- // ec.ContainerType and the lookup succeeds with the latter one,
- // then we are in this situation.
- mi = TypeManager.MemberLookup (
- ec.ContainerType, ec.ContainerType, ec.ContainerType,
- AllMemberTypes, AllBindingFlags, name);
-
- if (mi != null) {
- Report.Error (
- 1540, loc, "Cannot access protected member `" +
- TypeManager.CSharpName (qualifier_type) + "." +
- name + "' " + "via a qualifier of type `" +
- TypeManager.CSharpName (qualifier_type) + "'; the " +
- "qualifier must be of type `" +
- TypeManager.CSharpName (ec.ContainerType) + "' " +
- "(or derived from it)");
- return;
- }
- }
if (qualifier_type != null)
Report.Error_T (122, loc, TypeManager.CSharpName (qualifier_type) + "." + name);
oa = f.GetObsoleteAttribute (ec.DeclSpace);
if (oa != null)
AttributeTester.Report_ObsoleteMessage (oa, f.GetSignatureForError (), loc);
- } else {
+ // To be sure that type is external because we do not register generated fields
+ } else if (!(FieldInfo.DeclaringType is TypeBuilder)) {
oa = AttributeTester.GetMemberObsoleteAttribute (FieldInfo);
if (oa != null)
AttributeTester.Report_ObsoleteMessage (oa, TypeManager.GetFullNameSignature (FieldInfo), loc);
for (; current != null; current = current.BaseType) {
MemberInfo[] group = TypeManager.MemberLookup (
invocation_type, invocation_type, current,
- MemberTypes.Property, flags, PropertyInfo.Name);
+ MemberTypes.Property, flags, PropertyInfo.Name, null);
if (group == null)
continue;
}
}
+ /// <summary>
+ /// This checks the ConditionalAttribute on the method
+ /// </summary>
+ static bool IsMethodExcluded (MethodBase method, EmitContext ec)
+ {
+ if (method.IsConstructor)
+ return false;
+
+ IMethodData md = TypeManager.GetMethod (method);
+ if (md != null)
+ return md.IsExcluded (ec);
+
+ // For some methods (generated by delegate class) GetMethod returns null
+ // because they are not included in builder_to_method table
+ if (method.DeclaringType is TypeBuilder)
+ return false;
+
+ return AttributeTester.IsConditionalMethodExcluded (method);
+ }
+
/// <remarks>
/// is_base tells whether we want to force the use of the `call'
/// opcode instead of using callvirt. Call is required to call
}
- //
- // This checks the `ConditionalAttribute' on the method
- //
- TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method);
- if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+ oa = AttributeTester.GetObsoleteAttribute (method.DeclaringType);
+ if (oa != null) {
+ AttributeTester.Report_ObsoleteMessage (oa, method.DeclaringType.FullName, loc);
+ }
+
+ if (IsMethodExcluded (method, ec))
return;
if (!is_static){
return this;
Expression ml;
- ml = MemberLookupFinal (ec, null, type, ".ctor",
+ ml = MemberLookupFinal (ec, type, type, ".ctor",
+ // For member-lookup, treat 'new Foo (bar)' as call to 'foo.ctor (bar)', where 'foo' is of type 'Foo'.
MemberTypes.Constructor,
AllBindingFlags | BindingFlags.DeclaredOnly, loc);
/// initialization data and the other which does not need dimensions
/// specified but where initialization data is mandatory.
/// </remarks>
- public class ArrayCreation : ExpressionStatement {
+ public class ArrayCreation : Expression {
Expression requested_base_type;
ArrayList initializers;
//
// Emits the initializers for the array
//
- void EmitStaticInitializers (EmitContext ec, bool is_expression)
+ void EmitStaticInitializers (EmitContext ec)
{
//
// First, the static data
fb = RootContext.MakeStaticData (data);
- if (is_expression)
- ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Dup);
ig.Emit (OpCodes.Ldtoken, fb);
ig.Emit (OpCodes.Call,
TypeManager.void_initializearray_array_fieldhandle);
//
// This always expect the top value on the stack to be the array
//
- void EmitDynamicInitializers (EmitContext ec, bool is_expression)
+ void EmitDynamicInitializers (EmitContext ec)
{
ILGenerator ig = ec.ig;
int dims = bounds.Count;
num_automatic_initializers <= max_automatic_initializers) {
Type etype = e.Type;
- if (is_expression || i != top - 1)
- ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Dup);
for (int idx = 0; idx < dims; idx++)
IntConstant.EmitInt (ig, current_pos [idx]);
}
}
- void DoEmit (EmitContext ec, bool is_statement)
+ public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
// initialized. num_automatic_initializers will always be zero. See
// CheckIndices.
if (num_automatic_initializers > max_automatic_initializers)
- EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
+ EmitStaticInitializers (ec);
if (dynamic_initializers)
- EmitDynamicInitializers (ec, !is_statement);
+ EmitDynamicInitializers (ec);
}
}
- public override void Emit (EmitContext ec)
- {
- DoEmit (ec, false);
- }
-
- public override void EmitStatement (EmitContext ec)
- {
- DoEmit (ec, true);
- }
-
public object EncodeAsAttribute ()
{
if (!is_one_dimensional){
MemberInfo [] mi = TypeManager.MemberLookup (
caller_type, caller_type, lookup_type, MemberTypes.Property,
BindingFlags.Public | BindingFlags.Instance |
- BindingFlags.DeclaredOnly, p_name);
+ BindingFlags.DeclaredOnly, p_name, null);
if (mi == null || mi.Length == 0)
return null;
switch (error_no) {
case 0122: return "'{0}' is inaccessible due to its protection level";
case 0160: return "A previous catch clause already catches all exceptions of this or a super type '{0}'";
+ case 0601: return "The DllImport attribute must be specified on a method marked `static' and `extern'";
case 0619: return "'{0}' is obsolete: '{1}'";
+ case 0626: return "Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation";
case 0657: return "'{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '{1}'";
case 3001: return "Argument type '{0}' is not CLS-compliant";
case 3002: return "Return type of '{0}' is not CLS-compliant";
static public Type activator_type;
static public Type invalid_operation_exception_type;
static public Type obsolete_attribute_type;
- static public object conditional_attribute_type;
+ static public Type conditional_attribute_type;
static public Type in_attribute_type;
static public Type cls_compliant_attribute_type;
static public Type typed_reference_type;
/// </summary>
static public string GetFullNameSignature (MemberInfo mi)
{
- string n = mi.Name;
- if (n == ".ctor")
- n = mi.DeclaringType.Name;
+ return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + mi.Name;
+ }
- return mi.DeclaringType.FullName.Replace ('+', '.') + '.' + n;
+ static public string GetFullNameSignature (MethodBase mb)
+ {
+ string name = mb.Name;
+ if (name == ".ctor")
+ name = mb.DeclaringType.Name;
+
+ if (mb.IsSpecialName) {
+ if (name.StartsWith ("get_") || name.StartsWith ("set_")) {
+ name = name.Remove (0, 4);
+ }
+
+ if (name == "Item")
+ name = "this";
+ }
+
+ return mb.DeclaringType.FullName.Replace ('+', '.') + '.' + name;
}
static public string GetFullName (Type t)
/// </summary>
static public string CSharpSignature (MethodBase mb)
{
- string sig = "(";
+ StringBuilder sig = new StringBuilder ("(");
//
// FIXME: We should really have a single function to do
if (iparams == null)
iparams = new ReflectionParameters (mb);
+ // Is property
+ if (mb.IsSpecialName && iparams.Count == 0)
+ return GetFullNameSignature (mb);
+
for (int i = 0; i < iparams.Count; i++) {
if (i > 0) {
- sig += ", ";
+ sig.Append (", ");
}
- sig += iparams.ParameterDesc(i);
+ sig.Append (iparams.ParameterDesc (i));
}
- sig += ")";
+ sig.Append (")");
- return GetFullNameSignature (mb) + sig;
+ // Is indexer
+ if (mb.IsSpecialName && iparams.Count == 1) {
+ sig.Replace ('(', '[');
+ sig.Replace (')', ']');
+ }
+
+ return GetFullNameSignature (mb) + sig.ToString ();
}
/// <summary>
return target_list;
}
- [Flags]
- public enum MethodFlags {
- ShouldIgnore = 1 << 2
- }
-
static public bool IsGenericMethod (MethodBase mb)
{
if (mb.DeclaringType is TypeBuilder) {
return mb.IsGenericMethodDefinition;
}
- //
- // Returns the TypeManager.MethodFlags for this method.
- // This emits an error 619 / warning 618 if the method is obsolete.
- // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
- //
- static public MethodFlags GetMethodFlags (MethodBase mb)
- {
- MethodFlags flags = 0;
-
- if (mb.Mono_IsInflatedMethod)
- mb = mb.GetGenericMethodDefinition ();
-
- if (mb.DeclaringType is TypeBuilder){
- IMethodData method = (IMethodData) builder_to_method [mb];
- if (method == null) {
- // FIXME: implement Obsolete attribute on Property,
- // Indexer and Event.
- return 0;
- }
-
- if (method.ShouldIgnore ())
- flags |= MethodFlags.ShouldIgnore;
-
- return flags;
- }
-
- object [] attrs = mb.GetCustomAttributes (true);
- foreach (object ta in attrs){
- if (!(ta is System.Attribute)){
- Console.WriteLine ("Unknown type in GetMethodFlags: " + ta);
- continue;
- }
- System.Attribute a = (System.Attribute) ta;
-
- //
- // Skip over conditional code.
- //
- if (a.TypeId == TypeManager.conditional_attribute_type){
- ConditionalAttribute ca = (ConditionalAttribute) a;
-
- if (RootContext.AllDefines [ca.ConditionString] == null)
- flags |= MethodFlags.ShouldIgnore;
- }
- }
-
- return flags;
- }
-
#region MemberLookup implementation
//
// Whether we allow private members in the result (since FindMembers
// uses NonPublic for both protected and private), we need to distinguish.
//
- static bool closure_private_ok;
- //
+ static internal bool FilterNone (MemberInfo m, object filter_criteria)
+ {
+ return true;
+ }
+
+ internal class Closure {
+ internal bool private_ok;
+
// Who is invoking us and which type is being queried currently.
- //
- static Type closure_invocation_type;
- static Type closure_qualifier_type;
+ internal Type invocation_type;
+ internal Type qualifier_type;
- //
// The assembly that defines the type is that is calling us
- //
- static Assembly closure_invocation_assembly;
+ internal Assembly invocation_assembly;
+ internal IList almost_match;
- static internal bool FilterNone (MemberInfo m, object filter_criteria)
+ private bool CheckValidFamilyAccess (bool is_static, MemberInfo m)
{
+ if (invocation_type == null)
+ return false;
+
+ Debug.Assert (IsSubclassOrNestedChildOf (invocation_type, m.DeclaringType));
+
+ if (is_static)
+ return true;
+
+ // A nested class has access to all the protected members visible to its parent.
+ if (qualifier_type != null
+ && TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
+ return true;
+
+ if (invocation_type == m.DeclaringType
+ || invocation_type.IsSubclassOf (m.DeclaringType)) {
+ // Although a derived class can access protected members of its base class
+ // it cannot do so through an instance of the base class (CS1540).
+ // => Ancestry should be: declaring_type ->* invocation_type ->* qualified_type
+ if (qualifier_type == null
+ || qualifier_type == invocation_type
+ || qualifier_type.IsSubclassOf (invocation_type))
return true;
}
+ if (almost_match != null)
+ almost_match.Add (m);
+ return false;
+ }
+
//
// This filter filters by name + whether it is ok to include private
// members in the search
//
- static internal bool FilterWithClosure (MemberInfo m, object filter_criteria)
+ internal bool Filter (MemberInfo m, object filter_criteria)
{
//
// Hack: we know that the filter criteria will always be in the `closure'
if ((filter_criteria != null) && (m.Name != (string) filter_criteria))
return false;
- if (((closure_qualifier_type == null) || (closure_qualifier_type == closure_invocation_type)) &&
- (closure_invocation_type != null) && IsEqual (m.DeclaringType, closure_invocation_type))
+ if (((qualifier_type == null) || (qualifier_type == invocation_type)) &&
+ (invocation_type != null) && IsEqual (m.DeclaringType, invocation_type))
return true;
//
MethodAttributes ma = mb.Attributes & MethodAttributes.MemberAccessMask;
if (ma == MethodAttributes.Private)
- return closure_private_ok ||
- IsEqual (closure_invocation_type, m.DeclaringType) ||
- IsNestedChildOf (closure_invocation_type, m.DeclaringType);
+ return private_ok ||
+ IsEqual (invocation_type, m.DeclaringType) ||
+ IsNestedChildOf (invocation_type, m.DeclaringType);
//
// FamAndAssem requires that we not only derivate, but we are on the
// same assembly.
//
if (ma == MethodAttributes.FamANDAssem){
- if (closure_invocation_assembly != mb.DeclaringType.Assembly)
+ if (invocation_assembly != mb.DeclaringType.Assembly)
return false;
}
// Assembly and FamORAssem succeed if we're in the same assembly.
if ((ma == MethodAttributes.Assembly) || (ma == MethodAttributes.FamORAssem)){
- if (closure_invocation_assembly == mb.DeclaringType.Assembly)
+ if (invocation_assembly == mb.DeclaringType.Assembly)
return true;
}
// Family and FamANDAssem require that we derive.
if ((ma == MethodAttributes.Family) || (ma == MethodAttributes.FamANDAssem)){
- if (closure_invocation_type == null)
+ if (invocation_type == null)
return false;
- if (!IsSubclassOrNestedChildOf (closure_invocation_type, mb.DeclaringType))
+ if (!IsSubclassOrNestedChildOf (invocation_type, mb.DeclaringType))
return false;
// Although a derived class can access protected members of its base class
// it cannot do so through an instance of the base class (CS1540).
- if (!mb.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
- (closure_qualifier_type != null) &&
- closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
- !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
+ if (!mb.IsStatic && (invocation_type != qualifier_type) &&
+ (qualifier_type != null) &&
+ invocation_type.IsSubclassOf (qualifier_type) &&
+ !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
return false;
return true;
FieldAttributes fa = fi.Attributes & FieldAttributes.FieldAccessMask;
if (fa == FieldAttributes.Private)
- return closure_private_ok ||
- IsEqual (closure_invocation_type, m.DeclaringType) ||
- IsNestedChildOf (closure_invocation_type, m.DeclaringType);
+ return private_ok ||
+ IsEqual (invocation_type, m.DeclaringType) ||
+ IsNestedChildOf (invocation_type, m.DeclaringType);
//
// FamAndAssem requires that we not only derivate, but we are on the
// same assembly.
//
if (fa == FieldAttributes.FamANDAssem){
- if (closure_invocation_assembly != fi.DeclaringType.Assembly)
+ if (invocation_assembly != fi.DeclaringType.Assembly)
return false;
}
// Assembly and FamORAssem succeed if we're in the same assembly.
if ((fa == FieldAttributes.Assembly) || (fa == FieldAttributes.FamORAssem)){
- if (closure_invocation_assembly == fi.DeclaringType.Assembly)
+ if (invocation_assembly == fi.DeclaringType.Assembly)
return true;
}
// Family and FamANDAssem require that we derive.
if ((fa == FieldAttributes.Family) || (fa == FieldAttributes.FamANDAssem)){
- if (closure_invocation_type == null)
+ if (invocation_type == null)
return false;
- if (!IsSubclassOrNestedChildOf (closure_invocation_type, fi.DeclaringType))
+ if (!IsSubclassOrNestedChildOf (invocation_type, fi.DeclaringType))
return false;
// Although a derived class can access protected members of its base class
// it cannot do so through an instance of the base class (CS1540).
- if (!fi.IsStatic && (closure_invocation_type != closure_qualifier_type) &&
- (closure_qualifier_type != null) &&
- closure_invocation_type.IsSubclassOf (closure_qualifier_type) &&
- !TypeManager.IsNestedChildOf (closure_invocation_type, closure_qualifier_type))
+ if (!fi.IsStatic && (invocation_type != qualifier_type) &&
+ (qualifier_type != null) &&
+ invocation_type.IsSubclassOf (qualifier_type) &&
+ !TypeManager.IsNestedChildOf (invocation_type, qualifier_type))
return false;
return true;
//
// EventInfos and PropertyInfos, return true because they lack permission
- // informaiton, so we need to check later on the methods.
+ // information, so we need to check later on the methods.
//
return true;
}
+ }
- static MemberFilter FilterWithClosure_delegate = new MemberFilter (FilterWithClosure);
+ static Closure closure = new Closure ();
+ static MemberFilter FilterWithClosure_delegate = new MemberFilter (closure.Filter);
static MemberFilter FilterNone_delegate = new MemberFilter (FilterNone);
//
// is allowed to access (using the specified `qualifier_type' if given); only use
// BindingFlags.NonPublic to bypass the permission check.
//
+ // The 'almost_match' argument is used for reporting error CS1540.
+ //
// Returns an array of a single element for everything but Methods/Constructors
// that might return multiple matches.
//
public static MemberInfo [] MemberLookup (Type invocation_type, Type qualifier_type,
Type queried_type, MemberTypes mt,
- BindingFlags original_bf, string name)
+ BindingFlags original_bf, string name, IList almost_match)
{
Timer.StartTimer (TimerType.MemberLookup);
MemberInfo[] retval = RealMemberLookup (invocation_type, qualifier_type,
- queried_type, mt, original_bf, name);
+ queried_type, mt, original_bf, name, almost_match);
Timer.StopTimer (TimerType.MemberLookup);
static MemberInfo [] RealMemberLookup (Type invocation_type, Type qualifier_type,
Type queried_type, MemberTypes mt,
- BindingFlags original_bf, string name)
+ BindingFlags original_bf, string name, IList almost_match)
{
BindingFlags bf = original_bf;
bool skip_iface_check = true, used_cache = false;
bool always_ok_flag = false;
- closure_invocation_type = invocation_type;
- closure_invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
- closure_qualifier_type = qualifier_type;
+ closure.invocation_type = invocation_type;
+ closure.invocation_assembly = invocation_type != null ? invocation_type.Assembly : null;
+ closure.qualifier_type = qualifier_type;
+ closure.almost_match = almost_match;
//
// If we are a nested class, we always have access to our container
else
bf = original_bf;
- closure_private_ok = (original_bf & BindingFlags.NonPublic) != 0;
+ closure.private_ok = (original_bf & BindingFlags.NonPublic) != 0;
Timer.StopTimer (TimerType.MemberLookup);
foreach (TypeExpr itype in ifaces){
MemberInfo [] x;
- x = MemberLookup (null, null, itype.Type, mt, bf, name);
+ x = MemberLookup (null, null, itype.Type, mt, bf, name, null);
if (x != null)
return x;
}