using System;
using System.Diagnostics;
-using System.Collections;
-using System.Collections.Specialized;
+using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
/// <summary>
/// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
/// </summary>
- public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa);
+ public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
/// <summary>
/// Returns one AttributeTarget for this element.
Arguments NamedArguments;
bool resolve_error;
+ bool arg_resolved;
readonly bool nameEscaped;
//
//
IMemberContext context;
- static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
+ public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
static Assembly orig_sec_assembly;
public static readonly object[] EmptyObject = new object [0];
- // non-null if named args present after Resolve () is called
- PropertyInfo [] prop_info_arr;
- FieldInfo [] field_info_arr;
- object [] field_values_arr;
- object [] prop_values_arr;
- object [] pos_values;
+ IList<KeyValuePair<MemberExpr, NamedArgument>> named_values;
- static PtrHashtable usage_attr_cache;
// Cache for parameter-less attributes
- static PtrHashtable att_cache;
+ static Dictionary<TypeSpec, MethodSpec> att_cache;
public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
{
public static void Reset ()
{
- usage_attr_cache = new PtrHashtable ();
- att_cache = new PtrHashtable ();
+ att_cache = new Dictionary<TypeSpec, MethodSpec> ();
}
//
target.OptAttributes = null;
}
- void Error_InvalidNamedArgument (NamedArgument name)
+ static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
{
- Report.Error (617, name.Name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
+ rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
"must be fields which are not readonly, static, const or read-write properties which are " +
"public and not static",
- name.Name.Value);
+ name.Name);
}
- void Error_InvalidNamedArgumentType (NamedArgument name)
+ static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
{
- Report.Error (655, name.Name.Location,
+ rc.Report.Error (655, name.Location,
"`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
- name.Name.Value);
+ name.Name);
}
- public static void Error_AttributeArgumentNotValid (Location loc)
+ public static void Error_AttributeArgumentNotValid (IMemberContext rc, Location loc)
{
- Report.Error (182, loc,
+ rc.Compiler.Report.Error (182, loc,
"An attribute argument must be a constant expression, typeof " +
"expression or array creation expression");
}
Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
}
+ public void Error_MisusedDynamicAttribute ()
+ {
+ Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
+ }
+
/// <summary>
/// This is rather hack. We report many emit attribute error with same error to be compatible with
/// csc. But because csc has to report them this way because error came from ilasm we needn't.
return expr.ResolveAsTypeTerminal (ec, false);
}
- Type ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
+ TypeSpec ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
{
TypeExpr te = ResolveAsTypeTerminal (expr, context);
if (te == null)
return null;
- Type t = te.Type;
- if (TypeManager.IsSubclassOf (t, TypeManager.attribute_type)) {
+ TypeSpec t = te.Type;
+ if (t.IsAttribute) {
is_attr = true;
} else {
Report.SymbolRelatedToPreviousError (t);
/// </summary>
void ResolveAttributeType ()
{
- Report.IMessageRecorder msg_recorder = new Report.MessageRecorder ();
- Report.IMessageRecorder prev_recorder = Report.SetMessageRecorder (msg_recorder);
- int errors = Report.Errors;
+ SessionReportPrinter resolve_printer = new SessionReportPrinter ();
+ ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);
bool t1_is_attr = false;
- Type t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
-
bool t2_is_attr = false;
- Type t2;
+ TypeSpec t1, t2;
ATypeNameExpression expanded = null;
- if (nameEscaped) {
- t2 = null;
- } else {
- expanded = (ATypeNameExpression) expression.Clone (null);
- expanded.Name += "Attribute";
+ try {
+ t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
- t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
- }
+ if (nameEscaped) {
+ t2 = null;
+ } else {
+ expanded = (ATypeNameExpression) expression.Clone (null);
+ expanded.Name += "Attribute";
- msg_recorder.EndSession ();
- Report.SetMessageRecorder (prev_recorder);
- Report.Errors = errors;
+ t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
+ }
+
+ resolve_printer.EndSession ();
+ } finally {
+ context.Compiler.Report.SetPrinter (prev_recorder);
+ }
if (t1_is_attr && t2_is_attr) {
Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
return;
}
- msg_recorder.PrintMessages ();
+ resolve_printer.Merge (prev_recorder);
resolve_error = true;
}
- public virtual Type ResolveType ()
+ public virtual TypeSpec ResolveType ()
{
if (Type == null && !resolve_error)
ResolveAttributeType ();
return HasSecurityAttribute && IsSecurityActionValid (false);
}
- static bool IsValidArgumentType (Type t)
+ static bool IsValidArgumentType (TypeSpec t)
{
if (t.IsArray)
t = TypeManager.GetElementType (t);
get { return expression.Name; }
}
- void ApplyModuleCharSet ()
+ void ApplyModuleCharSet (ResolveContext rc)
{
if (Type != PredefinedAttributes.Get.DllImport)
return;
NamedArguments = new Arguments (1);
} else {
foreach (NamedArgument a in NamedArguments) {
- if (a.Name.Value == CharSetEnumMember)
+ if (a.Name == CharSetEnumMember)
return;
}
}
-
- NamedArguments.Add (new NamedArgument (new LocatedToken (loc, CharSetEnumMember),
- Constant.CreateConstant (typeof (CharSet), RootContext.ToplevelTypes.DefaultCharSet, Location)));
+
+ var char_set = Import.ImportType (typeof (CharSet));
+ NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
+ Constant.CreateConstant (rc, char_set, RootContext.ToplevelTypes.DefaultCharSet, Location)));
}
- public CustomAttributeBuilder Resolve ()
+ public Report Report {
+ get { return context.Compiler.Report; }
+ }
+
+ public MethodSpec Resolve ()
{
if (resolve_error)
return null;
resolve_error = true;
+ arg_resolved = true;
if (Type == null) {
ResolveAttributeType ();
return null;
}
- ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (Type);
+ ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
if (obsolete_attr != null) {
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location);
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
}
+ MethodSpec ctor;
+ // Try if the attribute is simple has been resolved before
if (PosArguments == null && NamedArguments == null) {
- object o = att_cache [Type];
- if (o != null) {
+ if (att_cache.TryGetValue (Type, out ctor)) {
resolve_error = false;
- return (CustomAttributeBuilder)o;
+ return ctor;
}
}
- ResolveContext rc = new ResolveContext (context, EmitContext.Options.ConstantScope);
- ConstructorInfo ctor = ResolveConstructor (rc);
+ ResolveContext rc = new ResolveContext (context, ResolveContext.Options.ConstantScope);
+ ctor = ResolveConstructor (rc);
if (ctor == null) {
- if (Type is TypeBuilder &&
- TypeManager.LookupDeclSpace (Type).MemberCache == null)
- // The attribute type has been DefineType'd, but not Defined. Let's not treat it as an error.
- // It'll be resolved again when the attached-to entity is emitted.
- resolve_error = false;
return null;
}
- ApplyModuleCharSet ();
-
- CustomAttributeBuilder cb;
- try {
- // SRE does not allow private ctor but we want to report all source code errors
- if (ctor.IsPrivate)
- return null;
-
- if (NamedArguments == null) {
- cb = new CustomAttributeBuilder (ctor, pos_values);
+ ApplyModuleCharSet (rc);
- if (pos_values.Length == 0)
- att_cache.Add (Type, cb);
-
- resolve_error = false;
- return cb;
- }
-
- if (!ResolveNamedArguments (rc)) {
- return null;
- }
-
- cb = new CustomAttributeBuilder (ctor, pos_values,
- prop_info_arr, prop_values_arr,
- field_info_arr, field_values_arr);
-
- resolve_error = false;
- return cb;
- }
- catch (Exception) {
- Error_AttributeArgumentNotValid (Location);
+ if (NamedArguments != null && !ResolveNamedArguments (rc)) {
return null;
}
+
+ resolve_error = false;
+ return ctor;
}
- protected virtual ConstructorInfo ResolveConstructor (ResolveContext ec)
+ protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
{
if (PosArguments != null) {
bool dynamic;
PosArguments.Resolve (ec, out dynamic);
- if (dynamic)
- throw new NotImplementedException ("dynamic");
+ if (dynamic) {
+ Error_AttributeArgumentNotValid (ec, loc);
+ return null;
+ }
}
MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
- Type, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
- BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+ Type, ConstructorInfo.ConstructorName, 0, MemberKind.Constructor,
+ BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly,
Location) as MethodGroupExpr;
if (mg == null)
if (mg == null)
return null;
- ConstructorInfo constructor = (ConstructorInfo)mg;
- if (PosArguments == null) {
- pos_values = EmptyObject;
- return constructor;
- }
-
- AParametersCollection pd = TypeManager.GetParameterData (constructor);
-
- if (!PosArguments.GetAttributableValue (ec, out pos_values))
- return null;
-
- // Here we do the checks which should be done by corlib or by runtime.
- // However Zoltan doesn't like it and every Mono compiler has to do it again.
- PredefinedAttributes pa = PredefinedAttributes.Get;
- if (Type == pa.Guid) {
- try {
- new Guid ((string)pos_values [0]);
- }
- catch (Exception e) {
- Error_AttributeEmitError (e.Message);
- return null;
- }
- }
-
- if (Type == pa.AttributeUsage && (int)pos_values [0] == 0) {
- Report.Error (591, Location, "Invalid value for argument to `System.AttributeUsage' attribute");
- return null;
- }
-
- if (Type == pa.IndexerName || Type == pa.Conditional) {
- string v = pos_values [0] as string;
- if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
- Report.Error (633, PosArguments [0].Expr.Location,
- "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
- return null;
- }
- }
-
- if (Type == pa.MethodImpl && pos_values.Length == 1 &&
- pd.Types [0] == TypeManager.short_type &&
- !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
- Error_AttributeEmitError ("Incorrect argument value.");
- return null;
- }
-
+ var constructor = (MethodSpec) mg;
return constructor;
}
protected virtual bool ResolveNamedArguments (ResolveContext ec)
{
int named_arg_count = NamedArguments.Count;
+ var seen_names = new List<string> (named_arg_count);
- ArrayList field_infos = new ArrayList (named_arg_count);
- ArrayList prop_infos = new ArrayList (named_arg_count);
- ArrayList field_values = new ArrayList (named_arg_count);
- ArrayList prop_values = new ArrayList (named_arg_count);
-
- ArrayList seen_names = new ArrayList (named_arg_count);
+ named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
foreach (NamedArgument a in NamedArguments) {
- string name = a.Name.Value;
+ string name = a.Name;
if (seen_names.Contains (name)) {
- Report.Error (643, a.Name.Location, "Duplicate named attribute `{0}' argument", name);
+ ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
continue;
}
a.Resolve (ec);
- Expression member = Expression.MemberLookup (
- ec.CurrentType, Type, name,
- MemberTypes.All,
- BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
+ Expression member = Expression.MemberLookup (ec.Compiler,
+ ec.CurrentType, Type, name, 0,
+ MemberKind.All,
+ BindingRestriction.AccessibleOnly,
Location);
if (member == null) {
- member = Expression.MemberLookup (ec.CurrentType, Type, name,
- MemberTypes.All, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
+ member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name, 0,
+ MemberKind.All, BindingRestriction.None,
Location);
if (member != null) {
- Report.SymbolRelatedToPreviousError (member.Type);
- Expression.ErrorIsInaccesible (Location, member.GetSignatureForError ());
+ ec.Report.SymbolRelatedToPreviousError (member.Type);
+ Expression.ErrorIsInaccesible (Location, member.GetSignatureForError (), ec.Report);
return false;
}
}
if (member == null){
- Expression.Error_TypeDoesNotContainDefinition (Location, Type, name);
+ Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
return false;
}
if (!(member is PropertyExpr || member is FieldExpr)) {
- Error_InvalidNamedArgument (a);
+ Error_InvalidNamedArgument (ec, a);
return false;
}
ObsoleteAttribute obsolete_attr;
if (member is PropertyExpr) {
- PropertyInfo pi = ((PropertyExpr) member).PropertyInfo;
+ var pi = ((PropertyExpr) member).PropertyInfo;
- if (!pi.CanWrite || !pi.CanRead || pi.GetGetMethod ().IsStatic) {
- Report.SymbolRelatedToPreviousError (pi);
- Error_InvalidNamedArgument (a);
+ if (!pi.HasSet || !pi.HasGet || pi.IsStatic) {
+ ec.Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedArgument (ec, a);
return false;
}
if (!IsValidArgumentType (member.Type)) {
- Report.SymbolRelatedToPreviousError (pi);
- Error_InvalidNamedArgumentType (a);
+ ec.Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedArgumentType (ec, a);
return false;
}
- object value;
- if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
- return false;
-
- PropertyBase pb = TypeManager.GetProperty (pi);
- if (pb != null)
- obsolete_attr = pb.GetObsoleteAttribute ();
- else
- obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (pi);
-
- prop_values.Add (value);
- prop_infos.Add (pi);
-
+ obsolete_attr = pi.GetAttributeObsolete ();
} else {
- FieldInfo fi = ((FieldExpr) member).FieldInfo;
+ var fi = ((FieldExpr) member).Spec;
- if (fi.IsInitOnly || fi.IsStatic) {
- Error_InvalidNamedArgument (a);
+ if (fi.IsReadOnly || fi.IsStatic) {
+ Error_InvalidNamedArgument (ec, a);
return false;
}
if (!IsValidArgumentType (member.Type)) {
- Report.SymbolRelatedToPreviousError (fi);
- Error_InvalidNamedArgumentType (a);
+ ec.Report.SymbolRelatedToPreviousError (fi);
+ Error_InvalidNamedArgumentType (ec, a);
return false;
}
- object value;
- if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
- return false;
+ obsolete_attr = fi.GetAttributeObsolete ();
+ }
- FieldBase fb = TypeManager.GetField (fi);
- if (fb != null)
- obsolete_attr = fb.GetObsoleteAttribute ();
- else
- obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi);
+ if (obsolete_attr != null && !context.IsObsolete)
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
- field_values.Add (value);
- field_infos.Add (fi);
+ if (a.Type != member.Type) {
+ a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
}
- if (obsolete_attr != null && !context.IsInObsoleteScope)
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
+ if (a.Expr != null)
+ named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
}
- prop_info_arr = new PropertyInfo [prop_infos.Count];
- field_info_arr = new FieldInfo [field_infos.Count];
- field_values_arr = new object [field_values.Count];
- prop_values_arr = new object [prop_values.Count];
-
- field_infos.CopyTo (field_info_arr, 0);
- field_values.CopyTo (field_values_arr, 0);
-
- prop_values.CopyTo (prop_values_arr, 0);
- prop_infos.CopyTo (prop_info_arr, 0);
-
return true;
}
public string GetValidTargets ()
{
StringBuilder sb = new StringBuilder ();
- AttributeTargets targets = GetAttributeUsage (Type).ValidOn;
+ AttributeTargets targets = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage).ValidOn;
if ((targets & AttributeTargets.Assembly) != 0)
sb.Append ("assembly, ");
if ((targets & AttributeTargets.ReturnValue) != 0)
sb.Append ("return, ");
-#if NET_2_0
if ((targets & AttributeTargets.GenericParameter) != 0)
sb.Append ("type parameter, ");
-#endif
- return sb.Remove (sb.Length - 2, 2).ToString ();
- }
- /// <summary>
- /// Returns AttributeUsage attribute based on types hierarchy
- /// </summary>
- static AttributeUsageAttribute GetAttributeUsage (Type type)
- {
- AttributeUsageAttribute ua = usage_attr_cache [type] as AttributeUsageAttribute;
- if (ua != null)
- return ua;
-
- Class attr_class = TypeManager.LookupClass (type);
- PredefinedAttribute pa = PredefinedAttributes.Get.AttributeUsage;
-
- if (attr_class == null) {
- if (!pa.IsDefined)
- return new AttributeUsageAttribute (0);
-
- object[] usage_attr = type.GetCustomAttributes (pa.Type, true);
- ua = (AttributeUsageAttribute)usage_attr [0];
- usage_attr_cache.Add (type, ua);
- return ua;
- }
-
- Attribute a = null;
- if (attr_class.OptAttributes != null)
- a = attr_class.OptAttributes.Search (pa);
-
- if (a == null) {
- if (attr_class.TypeBuilder.BaseType != TypeManager.attribute_type)
- ua = GetAttributeUsage (attr_class.TypeBuilder.BaseType);
- else
- ua = DefaultUsageAttribute;
- } else {
- ua = a.GetAttributeUsageAttribute ();
- }
-
- usage_attr_cache.Add (type, ua);
- return ua;
+ return sb.Remove (sb.Length - 2, 2).ToString ();
}
- AttributeUsageAttribute GetAttributeUsageAttribute ()
+ public AttributeUsageAttribute GetAttributeUsageAttribute ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// 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 ();
if (resolve_error)
return DefaultUsageAttribute;
- AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)pos_values [0]);
+ AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
- object field = GetPropertyValue ("AllowMultiple");
+ var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
if (field != null)
- usage_attribute.AllowMultiple = (bool)field;
+ usage_attribute.AllowMultiple = field.Value;
- field = GetPropertyValue ("Inherited");
+ field = GetPropertyValue ("Inherited") as BoolConstant;
if (field != null)
- usage_attribute.Inherited = (bool)field;
+ usage_attribute.Inherited = field.Value;
return usage_attribute;
}
/// </summary>
public string GetIndexerAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// 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 ();
if (resolve_error)
return null;
- return pos_values [0] as string;
+ return ((Constant) PosArguments [0].Expr).GetValue () as string;
}
/// <summary>
/// </summary>
public string GetConditionalAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// 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 ();
if (resolve_error)
return null;
- return (string)pos_values [0];
+ return ((Constant) PosArguments[0].Expr).GetValue () as string;
}
/// <summary>
/// </summary>
public ObsoleteAttribute GetObsoleteAttribute ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// 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 ();
if (resolve_error)
return null;
- if (pos_values == null || pos_values.Length == 0)
+ if (PosArguments == null)
return new ObsoleteAttribute ();
- if (pos_values.Length == 1)
- return new ObsoleteAttribute ((string)pos_values [0]);
+ string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
+ if (PosArguments.Count == 1)
+ return new ObsoleteAttribute (msg);
- return new ObsoleteAttribute ((string)pos_values [0], (bool)pos_values [1]);
+ return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
}
/// <summary>
/// </summary>
public bool GetClsCompliantAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// 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 ();
if (resolve_error)
return false;
- return (bool)pos_values [0];
+ return ((BoolConstant) PosArguments[0].Expr).Value;
}
- public Type GetCoClassAttributeValue ()
+ public TypeSpec GetCoClassAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
Resolve ();
if (resolve_error)
return null;
- return (Type)pos_values [0];
+ return GetArgumentType ();
}
public bool CheckTarget ()
}
// TODO: we can skip the first item
- if (((IList) valid_targets).Contains (ExplicitTarget)) {
+ if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
switch (ExplicitTarget) {
case "return": Target = AttributeTargets.ReturnValue; return true;
case "param": Target = AttributeTargets.Parameter; return true;
System.Security.Permissions.SecurityAction GetSecurityActionValue ()
{
- return (SecurityAction)pos_values [0];
+ return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
}
/// <summary>
/// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
/// </summary>
/// <returns></returns>
- public void ExtractSecurityPermissionSet (ListDictionary permissions)
+ public void ExtractSecurityPermissionSet (Dictionary<SecurityAction, PermissionSet> permissions)
{
Type orig_assembly_type = null;
- if (TypeManager.LookupDeclSpace (Type) != null) {
+ if (Type.MemberDefinition is TypeContainer) {
if (!RootContext.StdLib) {
- orig_assembly_type = Type.GetType (Type.FullName);
+ orig_assembly_type = System.Type.GetType (Type.GetMetaInfo ().FullName);
} else {
string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
if (orig_version_path == null) {
orig_sec_assembly = Assembly.LoadFile (file);
}
- orig_assembly_type = orig_sec_assembly.GetType (Type.FullName, true);
+ orig_assembly_type = orig_sec_assembly.GetType (Type.GetMetaInfo ().FullName, true);
if (orig_assembly_type == null) {
Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
"was not found in previous version of assembly");
}
SecurityAttribute sa;
+ object[] args;
+
// For all non-selfreferencing security attributes we can avoid all hacks
if (orig_assembly_type == null) {
- sa = (SecurityAttribute) Activator.CreateInstance (Type, pos_values);
+ args = new object[PosArguments.Count];
+ for (int j = 0; j < args.Length; ++j) {
+ args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
+ }
+
+ sa = (SecurityAttribute) Activator.CreateInstance (Type.GetMetaInfo (), args);
- if (prop_info_arr != null) {
- for (int i = 0; i < prop_info_arr.Length; ++i) {
- PropertyInfo pi = prop_info_arr [i];
- pi.SetValue (sa, prop_values_arr [i], null);
+ if (named_values != null) {
+ for (int i = 0; i < named_values.Count; ++i) {
+ PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
+ pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
}
}
} else {
// HACK: All security attributes have same ctor syntax
- sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, new object[] { GetSecurityActionValue () } );
+ args = new object[] { GetSecurityActionValue () };
+ sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, args);
// All types are from newly created assembly but for invocation with old one we need to convert them
- if (prop_info_arr != null) {
- for (int i = 0; i < prop_info_arr.Length; ++i) {
- PropertyInfo emited_pi = prop_info_arr [i];
+ if (named_values != null) {
+ for (int i = 0; i < named_values.Count; ++i) {
+ PropertyInfo emited_pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
// FIXME: We are missing return type filter
// TODO: pi can be null
PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
- object old_instance = TypeManager.IsEnumType (pi.PropertyType) ?
- System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) :
- prop_values_arr [i];
-
- pi.SetValue (sa, old_instance, null);
+ pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
}
}
}
IPermission perm;
perm = sa.CreatePermission ();
- SecurityAction action = GetSecurityActionValue ();
+ SecurityAction action = (SecurityAction) args [0];
// IS is correct because for corlib we are using an instance from old corlib
if (!(perm is System.Security.CodeAccessPermission)) {
}
}
- PermissionSet ps = (PermissionSet)permissions [action];
- if (ps == null) {
+ PermissionSet ps;
+ if (!permissions.TryGetValue (action, out ps)) {
if (sa is PermissionSetAttribute)
ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
else
ps.AddPermission (perm);
}
- public object GetPropertyValue (string name)
+ public Constant GetPropertyValue (string name)
{
- if (prop_info_arr == null)
+ if (named_values == null)
return null;
- for (int i = 0; i < prop_info_arr.Length; ++i) {
- if (prop_info_arr [i].Name == name)
- return prop_values_arr [i];
+ for (int i = 0; i < named_values.Count; ++i) {
+ if (named_values [i].Value.Name == name)
+ return named_values [i].Value.Expr as Constant;
}
return null;
// and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
// However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
//
-#if !NET_2_0
+#if false
public UnmanagedMarshal GetMarshal (Attributable attr)
{
UnmanagedType UnmanagedType;
public CharSet GetCharSetValue ()
{
- return (CharSet)System.Enum.Parse (typeof (CharSet), pos_values [0].ToString ());
+ return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
}
public bool HasField (string fieldName)
{
- if (field_info_arr == null)
+ if (named_values == null)
return false;
- foreach (FieldInfo fi in field_info_arr) {
- if (fi.Name == fieldName)
+ foreach (var na in named_values) {
+ if (na.Value.Name == fieldName)
return true;
}
return false;
MethodImplOptions options;
- if (pos_values[0].GetType () != typeof (MethodImplOptions))
- options = (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values[0]);
+ if (PosArguments[0].Type.GetMetaInfo () != typeof (MethodImplOptions))
+ options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
else
- options = (MethodImplOptions)pos_values[0];
+ options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
return (options & MethodImplOptions.InternalCall) != 0;
}
public LayoutKind GetLayoutKindValue ()
{
- if (!RootContext.StdLib || pos_values [0].GetType () != typeof (LayoutKind))
- return (LayoutKind)System.Enum.ToObject (typeof (LayoutKind), pos_values [0]);
+ if (!RootContext.StdLib || PosArguments[0].Type.GetMetaInfo () != typeof (LayoutKind))
+ return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
- return (LayoutKind)pos_values [0];
+ return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
}
- public object GetParameterDefaultValue ()
+ public Constant GetParameterDefaultValue (out TypeSpec type)
{
- return pos_values [0];
+ var expr = PosArguments[0].Expr;
+
+ if (expr is TypeCast)
+ expr = ((TypeCast) expr).Child;
+
+ type = expr.Type;
+ return expr as Constant;
}
public override bool Equals (object obj)
public override int GetHashCode ()
{
- return base.GetHashCode ();
+ return type.GetHashCode () ^ Target.GetHashCode ();
}
/// <summary>
/// Emit attribute for Attributable symbol
/// </summary>
- public void Emit (ListDictionary allEmitted)
+ public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
{
- CustomAttributeBuilder cb = Resolve ();
- if (cb == null)
+ var ctor = Resolve ();
+ if (ctor == null)
return;
- AttributeUsageAttribute usage_attr = GetAttributeUsage (Type);
+ AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage);
if ((usage_attr.ValidOn & Target) == 0) {
Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
"It is valid on `{1}' declarations only",
return;
}
+ var predefined = PredefinedAttributes.Get;
+
+ AttributeEncoder encoder = new AttributeEncoder (false);
+
+ if (PosArguments != null) {
+ var param_types = ctor.Parameters.Types;
+ for (int j = 0; j < PosArguments.Count; ++j) {
+ var pt = param_types[j];
+ if (!IsValidArgumentType (pt)) {
+ Error_AttributeArgumentNotValid (context, loc);
+ return;
+ }
+
+ var arg_expr = PosArguments[j].Expr;
+ if (j == 0) {
+ if (Type == predefined.IndexerName || Type == predefined.Conditional) {
+ string v = ((StringConstant) arg_expr).Value;
+ if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
+ context.Compiler.Report.Error (633, arg_expr.Location,
+ "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
+ }
+ } else if (Type == predefined.Guid) {
+ try {
+ string v = ((StringConstant) arg_expr).Value;
+ new Guid (v);
+ } catch (Exception e) {
+ Error_AttributeEmitError (e.Message);
+ return;
+ }
+ } else if (Type == predefined.AttributeUsage) {
+ int v = ((IntConstant)((EnumConstant) arg_expr).Child).Value;
+ if (v == 0) {
+ context.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
+ "System.AttributeUsage");
+ }
+ } else if (Type == predefined.MethodImpl && pt == TypeManager.short_type &&
+ !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
+ Error_AttributeEmitError ("Incorrect argument value.");
+ return;
+ }
+ }
+
+ arg_expr.EncodeAttributeValue (context, encoder, pt);
+ }
+ }
+
+ if (named_values != null) {
+ encoder.Stream.Write ((ushort) named_values.Count);
+ foreach (var na in named_values) {
+ if (na.Key is FieldExpr)
+ encoder.Stream.Write ((byte) 0x53);
+ else
+ encoder.Stream.Write ((byte) 0x54);
+
+ encoder.Encode (na.Key.Type);
+ encoder.Encode (na.Value.Name);
+ na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
+ }
+ } else {
+ encoder.Stream.Write ((ushort) 0);
+ }
+
+ byte[] cdata = encoder.ToArray ();
+
try {
foreach (Attributable target in targets)
- target.ApplyAttributeBuilder (this, cb, PredefinedAttributes.Get);
+ target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
} catch (Exception e) {
Error_AttributeEmitError (e.Message);
return;
}
if (!usage_attr.AllowMultiple && allEmitted != null) {
- if (allEmitted.Contains (this)) {
- ArrayList a = allEmitted [this] as ArrayList;
+ if (allEmitted.ContainsKey (this)) {
+ var a = allEmitted [this];
if (a == null) {
- a = new ArrayList (2);
+ a = new List<Attribute> (2);
allEmitted [this] = a;
}
a.Add (this);
// Here we are testing attribute arguments for array usage (error 3016)
if (Owner.IsClsComplianceRequired ()) {
if (PosArguments != null)
- PosArguments.CheckArrayAsAttribute ();
+ PosArguments.CheckArrayAsAttribute (context.Compiler);
if (NamedArguments == null)
return;
- NamedArguments.CheckArrayAsAttribute ();
+ NamedArguments.CheckArrayAsAttribute (context.Compiler);
}
}
return false;
}
- public Type GetArgumentType ()
+ public TypeSpec GetArgumentType ()
{
TypeOf e = GetValue () as TypeOf;
if (e == null)
throw new NotSupportedException ("ET");
}
- public override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
throw new NotImplementedException ();
}
}
}
- protected override ConstructorInfo ResolveConstructor (ResolveContext ec)
+ protected override MethodSpec ResolveConstructor (ResolveContext ec)
{
try {
Enter ();
}
public class Attributes {
- public readonly ArrayList Attrs;
+ public readonly List<Attribute> Attrs;
public Attributes (Attribute a)
{
- Attrs = new ArrayList ();
+ Attrs = new List<Attribute> ();
Attrs.Add (a);
}
- public Attributes (ArrayList attrs)
+ public Attributes (List<Attribute> attrs)
{
Attrs = attrs;
}
- public void AddAttributes (ArrayList attrs)
+ public void AddAttributes (List<Attribute> attrs)
{
Attrs.AddRange (attrs);
}
public Attributes Clone ()
{
- ArrayList al = new ArrayList (Attrs.Count);
+ var al = new List<Attribute> (Attrs.Count);
foreach (Attribute a in Attrs)
al.Add (a.Clone ());
/// </summary>
public Attribute[] SearchMulti (PredefinedAttribute t)
{
- ArrayList ar = null;
+ List<Attribute> ar = null;
foreach (Attribute a in Attrs) {
if (a.ResolveType () == t) {
if (ar == null)
- ar = new ArrayList ();
+ ar = new List<Attribute> (Attrs.Count);
ar.Add (a);
}
}
- return ar == null ? null : ar.ToArray (typeof (Attribute)) as Attribute[];
+ return ar == null ? null : ar.ToArray ();
}
public void Emit ()
{
CheckTargets ();
- ListDictionary ld = Attrs.Count > 1 ? new ListDictionary () : null;
+ Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
foreach (Attribute a in Attrs)
a.Emit (ld);
if (ld == null || ld.Count == 0)
return;
- foreach (DictionaryEntry d in ld) {
+ foreach (var d in ld) {
if (d.Value == null)
continue;
- foreach (Attribute collision in (ArrayList)d.Value)
- Report.SymbolRelatedToPreviousError (collision.Location, "");
+ Attribute a = d.Key;
- Attribute a = (Attribute)d.Key;
- Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
+ foreach (Attribute collision in d.Value)
+ a.Report.SymbolRelatedToPreviousError (collision.Location, "");
+
+ a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
a.GetSignatureForError ());
}
}
}
}
- /// <summary>
- /// Helper class for attribute verification routine.
- /// </summary>
- sealed class AttributeTester
+ public struct AttributeEncoder
{
- static PtrHashtable analyzed_types;
- static PtrHashtable analyzed_types_obsolete;
- static PtrHashtable analyzed_member_obsolete;
- static PtrHashtable analyzed_method_excluded;
- static PtrHashtable fixed_buffer_cache;
+ public readonly BinaryWriter Stream;
- static object TRUE = new object ();
- static object FALSE = new object ();
+ public AttributeEncoder (bool empty)
+ {
+ if (empty) {
+ Stream = null;
+ return;
+ }
- static AttributeTester ()
+ Stream = new BinaryWriter (new MemoryStream ());
+ const ushort version = 1;
+ Stream.Write (version);
+ }
+
+ public void Encode (string value)
+ {
+ if (value == null)
+ throw new ArgumentNullException ();
+
+ var buf = Encoding.UTF8.GetBytes(value);
+ WriteCompressedValue (buf.Length);
+ Stream.Write (buf);
+ }
+
+ public void Encode (TypeSpec type)
+ {
+ if (type == TypeManager.bool_type) {
+ Stream.Write ((byte) 0x02);
+ } else if (type == TypeManager.char_type) {
+ Stream.Write ((byte) 0x03);
+ } else if (type == TypeManager.sbyte_type) {
+ Stream.Write ((byte) 0x04);
+ } else if (type == TypeManager.byte_type) {
+ Stream.Write ((byte) 0x05);
+ } else if (type == TypeManager.short_type) {
+ Stream.Write ((byte) 0x06);
+ } else if (type == TypeManager.ushort_type) {
+ Stream.Write ((byte) 0x07);
+ } else if (type == TypeManager.int32_type) {
+ Stream.Write ((byte) 0x08);
+ } else if (type == TypeManager.uint32_type) {
+ Stream.Write ((byte) 0x09);
+ } else if (type == TypeManager.int64_type) {
+ Stream.Write ((byte) 0x0A);
+ } else if (type == TypeManager.uint64_type) {
+ Stream.Write ((byte) 0x0B);
+ } else if (type == TypeManager.float_type) {
+ Stream.Write ((byte) 0x0C);
+ } else if (type == TypeManager.double_type) {
+ Stream.Write ((byte) 0x0D);
+ } else if (type == TypeManager.string_type) {
+ Stream.Write ((byte) 0x0E);
+ } else if (type == TypeManager.type_type) {
+ Stream.Write ((byte) 0x50);
+ } else if (type == TypeManager.object_type) {
+ Stream.Write ((byte) 0x51);
+ } else if (TypeManager.IsEnumType (type)) {
+ Stream.Write ((byte) 0x55);
+ EncodeTypeName (type);
+ } else if (type.IsArray) {
+ Stream.Write ((byte) 0x1D);
+ Encode (TypeManager.GetElementType (type));
+ } else {
+ throw new NotImplementedException (type.ToString ());
+ }
+ }
+
+ public bool EncodeTypeName (TypeSpec type)
{
- Reset ();
+// if (TypeManager.ContainsGenericParameters (type) && !TypeManager.IsGenericTypeDefinition (type))
+// return false;
+
+ var old_type = type.GetMetaInfo ();
+ Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
+ return true;
}
- private AttributeTester ()
+ void WriteCompressedValue (int value)
{
+ if (value < 0x80) {
+ Stream.Write ((byte) value);
+ return;
+ }
+
+ if (value < 0x4000) {
+ Stream.Write ((byte) (0x80 | (value >> 8)));
+ Stream.Write ((byte) value);
+ return;
+ }
+
+ Stream.Write (value);
}
- public static void Reset ()
+ public byte[] ToArray ()
{
- analyzed_types = new PtrHashtable ();
- analyzed_types_obsolete = new PtrHashtable ();
- analyzed_member_obsolete = new PtrHashtable ();
- analyzed_method_excluded = new PtrHashtable ();
- fixed_buffer_cache = new PtrHashtable ();
+ return ((MemoryStream) Stream.BaseStream).ToArray ();
}
+ }
+
+ /// <summary>
+ /// Helper class for attribute verification routine.
+ /// </summary>
+ static class AttributeTester
+ {
public enum Result {
Ok,
RefOutArrayError,
/// </summary>
public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
{
- Type [] types_a = pa.Types;
- Type [] types_b = pb.Types;
+ TypeSpec [] types_a = pa.Types;
+ TypeSpec [] types_b = pb.Types;
if (types_a == null || types_b == null)
return Result.Ok;
Result result = Result.Ok;
for (int i = 0; i < types_b.Length; ++i) {
- Type aType = types_a [i];
- Type bType = types_b [i];
+ TypeSpec aType = types_a [i];
+ TypeSpec bType = types_b [i];
+
+ var ac_a = aType as ArrayContainer;
+ var ac_b = aType as ArrayContainer;
- if (aType.IsArray && bType.IsArray) {
- Type a_el_type = TypeManager.GetElementType (aType);
- Type b_el_type = TypeManager.GetElementType (bType);
- if (aType.GetArrayRank () != bType.GetArrayRank () && a_el_type == b_el_type) {
+ if (ac_a != null && ac_b != null) {
+ if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
result = Result.RefOutArrayError;
continue;
}
- if (a_el_type.IsArray || b_el_type.IsArray) {
+ if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
result = Result.ArrayArrayError;
continue;
}
return result;
}
- /// <summary>
- /// This method tests the CLS compliance of external types. It doesn't test type visibility.
- /// </summary>
- public static bool IsClsCompliant (Type type)
- {
- if (type == null)
- return true;
-
- object type_compliance = analyzed_types[type];
- if (type_compliance != null)
- return type_compliance == TRUE;
-
- if (type.IsPointer) {
- analyzed_types.Add (type, FALSE);
- return false;
- }
-
- bool result;
- if (type.IsArray) {
- result = IsClsCompliant (TypeManager.GetElementType (type));
- } else if (TypeManager.IsNullableType (type)) {
- result = IsClsCompliant (TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (type) [0]));
- } else {
- result = AnalyzeTypeCompliance (type);
- }
- analyzed_types.Add (type, result ? TRUE : FALSE);
- return result;
- }
-
- /// <summary>
- /// Returns IFixedBuffer implementation if field is fixed buffer else null.
- /// </summary>
- public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
- {
- // Fixed buffer helper type is generated as value type
- if (TypeManager.IsReferenceType (fi.FieldType))
- return null;
-
- FieldBase fb = TypeManager.GetField (fi);
- if (fb != null) {
- return fb as IFixedBuffer;
- }
-
- if (TypeManager.GetConstant (fi) != null)
- return null;
-
- object o = fixed_buffer_cache [fi];
- if (o == null) {
- PredefinedAttribute pa = PredefinedAttributes.Get.FixedBuffer;
- if (!pa.IsDefined)
- return null;
-
- if (!fi.IsDefined (pa.Type, false)) {
- fixed_buffer_cache.Add (fi, FALSE);
- return null;
- }
-
- IFixedBuffer iff = new FixedFieldExternal (fi);
- fixed_buffer_cache.Add (fi, iff);
- return iff;
- }
-
- if (o == FALSE)
- return null;
-
- return (IFixedBuffer)o;
- }
-
- public static void VerifyModulesClsCompliance ()
+ public static void VerifyModulesClsCompliance (CompilerContext ctx)
{
Module[] modules = GlobalRootNamespace.Instance.Modules;
if (modules == null)
for (int i = 1; i < modules.Length; ++i) {
Module module = modules [i];
if (!GetClsCompliantAttributeValue (module, null)) {
- Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
+ ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
"to match the assembly", module.Name);
return;
}
}
}
- public static Type GetImportedIgnoreCaseClsType (string name)
- {
- foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
- Type t = a.GetType (name, false, true);
- if (t == null)
- continue;
-
- if (IsClsCompliant (t))
- return t;
- }
- return null;
- }
-
static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
{
- PredefinedAttribute pa = PredefinedAttributes.Get.CLSCompliant;
- if (!pa.IsDefined)
- return false;
-
- object[] cls_attr = attribute_provider.GetCustomAttributes (pa.Type, false);
+ object[] cls_attr = attribute_provider.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
if (cls_attr.Length == 0) {
if (a == null)
return false;
return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
}
- static bool AnalyzeTypeCompliance (Type type)
- {
- type = TypeManager.DropGenericTypeArguments (type);
- DeclSpace ds = TypeManager.LookupDeclSpace (type);
- if (ds != null) {
- return ds.IsClsComplianceRequired ();
- }
-
- if (TypeManager.IsGenericParameter (type))
- return true;
-
- return GetClsCompliantAttributeValue (type, type.Assembly);
- }
-
- /// <summary>
- /// Returns instance of ObsoleteAttribute when type is obsolete
- /// </summary>
- public static ObsoleteAttribute GetObsoleteAttribute (Type type)
- {
- object type_obsolete = analyzed_types_obsolete [type];
- if (type_obsolete == FALSE)
- return null;
-
- if (type_obsolete != null)
- return (ObsoleteAttribute)type_obsolete;
-
- ObsoleteAttribute result = null;
- if (TypeManager.HasElementType (type)) {
- result = GetObsoleteAttribute (TypeManager.GetElementType (type));
- } else if (TypeManager.IsGenericParameter (type))
- result = null; // TODO: throw new NotSupportedException ()
- else if (TypeManager.IsGenericType (type) && !TypeManager.IsGenericTypeDefinition (type)) {
- return GetObsoleteAttribute (TypeManager.DropGenericTypeArguments (type));
- } else {
- DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
-
- // Type is external, we can get attribute directly
- if (type_ds == null) {
- PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
- if (pa.IsDefined) {
- object[] attribute = type.GetCustomAttributes (pa.Type, false);
- if (attribute.Length == 1)
- result = (ObsoleteAttribute) attribute[0];
- }
- } else {
- result = type_ds.GetObsoleteAttribute ();
- }
- }
-
- // Cannot use .Add because of corlib bootstrap
- analyzed_types_obsolete [type] = result == null ? FALSE : result;
- return result;
- }
-
- /// <summary>
- /// Returns instance of ObsoleteAttribute when method is obsolete
- /// </summary>
- public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
- {
- IMethodData mc = TypeManager.GetMethod (mb);
- if (mc != null)
- return mc.GetObsoleteAttribute ();
-
- // compiler generated methods are not registered by AddMethod
- if (mb.DeclaringType is TypeBuilder)
- return null;
-
- MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb);
- if (mi != null)
- return GetMemberObsoleteAttribute (mi);
-
- mi = TypeManager.GetEventFromAccessor (mb);
- if (mi != null)
- return GetMemberObsoleteAttribute (mi);
-
- return GetMemberObsoleteAttribute (mb);
- }
-
- /// <summary>
- /// Returns instance of ObsoleteAttribute when member is obsolete
- /// </summary>
- public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
- {
- object type_obsolete = analyzed_member_obsolete [mi];
- if (type_obsolete == FALSE)
- return null;
-
- if (type_obsolete != null)
- return (ObsoleteAttribute)type_obsolete;
-
- if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
- return null;
-
- PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
- if (!pa.IsDefined)
- return null;
-
- ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false)
- as ObsoleteAttribute;
- analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa);
- return oa;
- }
-
/// <summary>
/// Common method for Obsolete error/warning reporting.
/// </summary>
- public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc)
+ public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
{
if (oa.IsError) {
Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
}
Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
}
-
- public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
- {
- object excluded = analyzed_method_excluded [mb];
- if (excluded != null)
- return excluded == TRUE ? true : false;
-
- PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
- if (!pa.IsDefined)
- return false;
-
- ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
- as ConditionalAttribute[];
- if (attrs.Length == 0) {
- analyzed_method_excluded.Add (mb, FALSE);
- return false;
- }
-
- foreach (ConditionalAttribute a in attrs) {
- if (loc.CompilationUnit.IsConditionalDefined (a.ConditionString)) {
- analyzed_method_excluded.Add (mb, FALSE);
- return false;
- }
- }
-
- analyzed_method_excluded.Add (mb, TRUE);
- return true;
- }
-
- /// <summary>
- /// Analyzes class whether it has attribute which has ConditionalAttribute
- /// and its condition is not defined.
- /// </summary>
- public static bool IsAttributeExcluded (Type type, Location loc)
- {
- if (!type.IsClass)
- return false;
-
- Class class_decl = TypeManager.LookupDeclSpace (type) as Class;
-
- // TODO: add caching
- // TODO: merge all Type bases attribute caching to one cache to save memory
- PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
- if (class_decl == null && pa.IsDefined) {
- object[] attributes = type.GetCustomAttributes (pa.Type, false);
- foreach (ConditionalAttribute ca in attributes) {
- if (loc.CompilationUnit.IsConditionalDefined (ca.ConditionString))
- return false;
- }
- return attributes.Length > 0;
- }
-
- return class_decl.IsExcluded ();
- }
-
- public static Type GetCoClassAttribute (Type type)
- {
- TypeContainer tc = TypeManager.LookupInterface (type);
- PredefinedAttribute pa = PredefinedAttributes.Get.CoClass;
- if (tc == null) {
- if (!pa.IsDefined)
- return null;
-
- object[] o = type.GetCustomAttributes (pa.Type, false);
- if (o.Length < 1)
- return null;
- return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
- }
-
- if (tc.OptAttributes == null)
- return null;
-
- Attribute a = tc.OptAttributes.Search (pa);
- if (a == null)
- return null;
-
- return a.GetCoClassAttributeValue ();
- }
}
public class PredefinedAttributes
// New in .NET 4.0
public readonly PredefinedAttribute Dynamic;
+ public readonly PredefinedAttribute DynamicTransform; // DynamicAttribute with transform arguments
//
// Optional types which are used as types and for member lookup
Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
+ DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
}
- public void Initialize ()
+ public void Initialize (CompilerContext ctx)
{
foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
- ((PredefinedAttribute) fi.GetValue (this)).Resolve (true);
+ ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
}
}
public class PredefinedAttribute
{
- Type type;
+ TypeSpec type;
CustomAttributeBuilder cab;
- ConstructorInfo ctor;
+ MethodSpec ctor;
readonly string ns, name;
+ CompilerContext compiler;
+
+ static readonly TypeSpec NotFound = InternalType.Null;
public PredefinedAttribute (string ns, string name)
{
this.name = name;
}
- public static bool operator == (Type type, PredefinedAttribute pa)
+ public static bool operator == (TypeSpec type, PredefinedAttribute pa)
{
return type == pa.type;
}
- public static bool operator != (Type type, PredefinedAttribute pa)
+ public static bool operator != (TypeSpec type, PredefinedAttribute pa)
{
return type != pa.type;
}
public ConstructorInfo Constructor {
- get { return ctor; }
+ get { return ctor == null ? null : (ConstructorInfo) ctor.GetMetaInfo (); }
}
public override int GetHashCode ()
return base.GetHashCode ();
}
+ public string GetSignatureForError ()
+ {
+ return ns + "." + name;
+ }
+
public override bool Equals (object obj)
{
throw new NotSupportedException ();
builder.SetCustomAttribute (cab);
}
- public void EmitAttribute (ParameterBuilder builder, Location loc)
+ public void EmitAttribute (ParameterBuilder builder)
{
if (ResolveBuilder ())
builder.SetCustomAttribute (cab);
}
public bool IsDefined {
- get { return type != null && type != typeof (PredefinedAttribute); }
+ get { return type != null && type != NotFound; }
+ }
+
+ public void Initialize (CompilerContext ctx, bool canFail)
+ {
+ this.compiler = ctx;
+ Resolve (canFail);
}
public bool Resolve (bool canFail)
return false;
}
- type = TypeManager.CoreLookupType (ns, name, Kind.Class, !canFail);
+ type = TypeManager.CoreLookupType (compiler, ns, name, MemberKind.Class, !canFail);
if (type == null) {
- type = typeof (PredefinedAttribute);
+ type = NotFound;
return false;
}
if (!Resolve (true))
return false;
- ConstructorInfo ci = TypeManager.GetPredefinedConstructor (type, Location.Null, Type.EmptyTypes);
+ var ci = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
if (ci == null)
return false;
- cab = new CustomAttributeBuilder (ci, new object[0]);
+ cab = new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0]);
return true;
}
- public bool ResolveConstructor (Location loc, params Type[] argType)
+ public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
{
if (ctor != null)
throw new InternalErrorException ("Predefined ctor redefined");
return ctor != null;
}
- public Type Type {
+ public TypeSpec Type {
get { return type; }
}
}