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;
/// Base class for objects that can have Attributes applied to them.
/// </summary>
public abstract class Attributable {
- /// <summary>
- /// Attributes for this type
- /// </summary>
+ //
+ // Holds all attributes attached to this element
+ //
protected Attributes attributes;
- public Attributable (Attributes attrs)
+ public void AddAttributes (Attributes attrs, IMemberContext context)
{
- if (attrs != null)
- OptAttributes = attrs;
+ if (attrs == null)
+ return;
+
+ if (attributes == null)
+ attributes = attrs;
+ else
+ throw new NotImplementedException ();
+
+ attributes.AttachTo (this, context);
}
- public Attributes OptAttributes
- {
+ public Attributes OptAttributes {
get {
return attributes;
}
set {
attributes = value;
-
- if (attributes != null) {
- attributes.AttachTo (this);
- }
}
}
/// </summary>
public abstract AttributeTargets AttributeTargets { get; }
- public abstract IResolveContext ResolveContext { get; }
-
public abstract bool IsClsComplianceRequired ();
/// <summary>
public class Attribute : Expression
{
- //
- // Wraps owner resolve context, the owner is an attribute
- // parent and the rest is exactly same
- //
- struct AttributeResolveContext : IResolveContext
- {
- readonly IResolveContext rc;
-
- public AttributeResolveContext (IResolveContext rc)
- {
- this.rc = rc;
- }
-
- #region IResolveContext Members
-
- public DeclSpace DeclContainer {
- get {
- DeclSpace ds = rc as DeclSpace;
- if (ds == null)
- return rc.DeclContainer;
-
- return ds;
- }
- }
-
- public bool IsInObsoleteScope {
- get { return rc.IsInObsoleteScope; }
- }
-
- public bool IsInUnsafeScope {
- get { return rc.IsInUnsafeScope; }
- }
-
- public DeclSpace GenericDeclContainer {
- get { return rc.GenericDeclContainer; }
- }
-
- #endregion
- }
-
public readonly string ExplicitTarget;
public AttributeTargets Target;
+ readonly ATypeNameExpression expression;
- // TODO: remove this member
- public readonly string Name;
- public readonly Expression LeftExpr;
- public readonly string Identifier;
-
- ArrayList PosArguments;
- ArrayList NamedArguments;
+ Arguments PosArguments;
+ Arguments NamedArguments;
bool resolve_error;
readonly bool nameEscaped;
- // It can contain more onwers when the attribute is applied to multiple fiels.
- protected Attributable[] owners;
+ //
+ // An attribute can be attached to multiple targets (e.g. multiple fields)
+ //
+ protected Attributable[] targets;
+
+ //
+ // A member context for the attribute, it's much easier to hold it here
+ // than trying to pull it during resolve
+ //
+ IMemberContext context;
static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
static Assembly orig_sec_assembly;
object [] prop_values_arr;
object [] pos_values;
- static PtrHashtable usage_attr_cache;
+ static Dictionary<Type, AttributeUsageAttribute> usage_attr_cache;
// Cache for parameter-less attributes
- static PtrHashtable att_cache;
-
- public Attribute (string target, Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped)
+ static Dictionary<Type, CustomAttributeBuilder> att_cache;
+
+ public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
{
- LeftExpr = left_expr;
- Identifier = identifier;
- Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
+ this.expression = expr;
if (args != null) {
- PosArguments = (ArrayList)args [0];
- NamedArguments = (ArrayList)args [1];
+ PosArguments = args [0];
+ NamedArguments = args [1];
}
this.loc = loc;
ExplicitTarget = target;
public Attribute Clone ()
{
- Attribute a = new Attribute (ExplicitTarget, LeftExpr, Identifier, null, loc, nameEscaped);
+ Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
a.PosArguments = PosArguments;
a.NamedArguments = NamedArguments;
return a;
public static void Reset ()
{
- usage_attr_cache = new PtrHashtable ();
- att_cache = new PtrHashtable ();
+ usage_attr_cache = new Dictionary<Type, AttributeUsageAttribute> (ReferenceEquality<Type>.Default);
+ att_cache = new Dictionary<Type, CustomAttributeBuilder> (ReferenceEquality<Type>.Default);
}
- public virtual void AttachTo (Attributable owner)
+ //
+ // When the same attribute is attached to multiple fiels
+ // we use @target field as a list of targets. The attribute
+ // has to be resolved only once but emitted for each target.
+ //
+ public virtual void AttachTo (Attributable target, IMemberContext context)
{
- if (this.owners == null) {
- this.owners = new Attributable[1] { owner };
+ if (this.targets == null) {
+ this.targets = new Attributable[] { target };
+ this.context = context;
return;
}
- // When the same attribute is attached to multiple fiels
- // we use this extra_owners as a list of owners. The attribute
- // then can be removed because will be emitted when first owner
- // is served
- Attributable[] new_array = new Attributable [this.owners.Length + 1];
- owners.CopyTo (new_array, 0);
- new_array [owners.Length] = owner;
- this.owners = new_array;
- owner.OptAttributes = null;
+ // Resize target array
+ Attributable[] new_array = new Attributable [this.targets.Length + 1];
+ targets.CopyTo (new_array, 0);
+ new_array [targets.Length] = target;
+ this.targets = new_array;
+
+ // No need to update context, different targets cannot have
+ // different contexts, it's enough to remove same attributes
+ // from secondary members.
+
+ target.OptAttributes = null;
}
- void Error_InvalidNamedArgument (string name)
+ static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
{
- Report.Error (617, 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.Name);
}
- void Error_InvalidNamedAgrumentType (string name)
+ static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
{
- Report.Error (655, Location, "`{0}' is not a valid named attribute argument because it is not a valid " +
- "attribute parameter type", name);
+ 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);
}
- public static void Error_AttributeArgumentNotValid (Location loc)
+ public static void Error_AttributeArgumentNotValid (ResolveContext rc, Location loc)
{
- Report.Error (182, loc,
+ rc.Report.Error (182, loc,
"An attribute argument must be a constant expression, typeof " +
"expression or array creation expression");
}
- static void Error_TypeParameterInAttribute (Location loc)
- {
- Report.Error (
- -202, loc, "Can not use a type parameter in an attribute");
- }
-
public void Error_MissingGuidAttribute ()
{
Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
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.
Attributable Owner {
get {
- return owners [0];
+ return targets [0];
}
}
- protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
+ protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
{
- return expr.ResolveAsTypeTerminal (ec, silent);
+ return expr.ResolveAsTypeTerminal (ec, false);
}
- Type ResolvePossibleAttributeType (string name, bool silent, ref bool is_attr)
+ Type ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
{
- IResolveContext rc = new AttributeResolveContext (Owner.ResolveContext);
-
- TypeExpr te;
- if (LeftExpr == null) {
- te = ResolveAsTypeTerminal (new SimpleName (name, Location), rc, silent);
- } else {
- te = ResolveAsTypeTerminal (new MemberAccess (LeftExpr, name), rc, silent);
- }
-
+ TypeExpr te = ResolveAsTypeTerminal (expr, context);
if (te == null)
return null;
Type t = te.Type;
if (TypeManager.IsSubclassOf (t, TypeManager.attribute_type)) {
is_attr = true;
- } else if (!silent) {
+ } else {
Report.SymbolRelatedToPreviousError (t);
Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
}
/// </summary>
void ResolveAttributeType ()
{
- bool t1_is_attr = false;
- Type t1 = ResolvePossibleAttributeType (Identifier, true, ref t1_is_attr);
+ SessionReportPrinter resolve_printer = new SessionReportPrinter ();
+ ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);
+ bool t1_is_attr = false;
bool t2_is_attr = false;
- Type t2 = nameEscaped ? null :
- ResolvePossibleAttributeType (Identifier + "Attribute", true, ref t2_is_attr);
+ Type t1, t2;
+ ATypeNameExpression expanded = null;
+
+ try {
+ t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
+
+ if (nameEscaped) {
+ t2 = null;
+ } else {
+ expanded = (ATypeNameExpression) expression.Clone (null);
+ expanded.Name += "Attribute";
+
+ 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 `{0}' and `{0}Attribute'. " +
- "Use either `@{0}' or `{0}Attribute'", GetSignatureForError ());
+ Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
+ GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
resolve_error = true;
return;
}
return;
}
- if (t1 == null && t2 == null)
- ResolvePossibleAttributeType (Identifier, false, ref t1_is_attr);
- if (t1 != null)
- ResolvePossibleAttributeType (Identifier, false, ref t1_is_attr);
- if (t2 != null)
- ResolvePossibleAttributeType (Identifier + "Attribute", false, ref t2_is_attr);
-
+ resolve_printer.Merge (prev_recorder);
resolve_error = true;
}
if (Type != null)
return TypeManager.CSharpName (Type);
- return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier;
+ return expression.GetSignatureForError ();
}
public bool HasSecurityAttribute {
t == TypeManager.type_type;
}
- [Conditional ("GMCS_SOURCE")]
- void ApplyModuleCharSet ()
+ // TODO: Don't use this ambiguous value
+ public string Name {
+ get { return expression.Name; }
+ }
+
+ void ApplyModuleCharSet (ResolveContext rc)
{
if (Type != PredefinedAttributes.Get.DllImport)
return;
const string CharSetEnumMember = "CharSet";
if (NamedArguments == null) {
- NamedArguments = new ArrayList (1);
+ NamedArguments = new Arguments (1);
} else {
- foreach (DictionaryEntry de in NamedArguments) {
- if ((string)de.Key == CharSetEnumMember)
+ foreach (NamedArgument a in NamedArguments) {
+ if (a.Name == CharSetEnumMember)
return;
}
}
- NamedArguments.Add (new DictionaryEntry (CharSetEnumMember,
- new Argument (Constant.CreateConstant (typeof (CharSet), RootContext.ToplevelTypes.DefaultCharSet, Location))));
+ NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
+ Constant.CreateConstant (rc, typeof (CharSet), RootContext.ToplevelTypes.DefaultCharSet, Location)));
}
+ public Report Report {
+ get { return context.Compiler.Report; }
+ }
+
public CustomAttributeBuilder Resolve ()
{
if (resolve_error)
ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (Type);
if (obsolete_attr != null) {
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location);
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
}
+ CustomAttributeBuilder cb;
if (PosArguments == null && NamedArguments == null) {
- object o = att_cache [Type];
- if (o != null) {
+ if (att_cache.TryGetValue (Type, out cb)) {
resolve_error = false;
- return (CustomAttributeBuilder)o;
+ return cb;
}
}
- Attributable owner = Owner;
- DeclSpace ds = owner.ResolveContext as DeclSpace;
- if (ds == null)
- ds = owner.ResolveContext.DeclContainer;
-
- EmitContext ec = new EmitContext (owner.ResolveContext, ds, ds,
- Location, null, typeof (Attribute), ds.ModFlags, false);
- ec.IsAnonymousMethodAllowed = false;
-
- ConstructorInfo ctor = ResolveConstructor (ec);
+ ResolveContext rc = new ResolveContext (context, ResolveContext.Options.ConstantScope);
+ var ctor = ResolveConstructor (rc);
if (ctor == null) {
if (Type is TypeBuilder &&
TypeManager.LookupDeclSpace (Type).MemberCache == null)
return null;
}
- ApplyModuleCharSet ();
+ ApplyModuleCharSet (rc);
- CustomAttributeBuilder cb;
try {
+ var ctor_meta = (ConstructorInfo) ctor.MetaInfo;
// SRE does not allow private ctor but we want to report all source code errors
- if (ctor.IsPrivate)
+ if (ctor.MetaInfo.IsPrivate)
return null;
if (NamedArguments == null) {
- cb = new CustomAttributeBuilder (ctor, pos_values);
+ cb = new CustomAttributeBuilder (ctor_meta, pos_values);
if (pos_values.Length == 0)
att_cache.Add (Type, cb);
return cb;
}
- if (!ResolveNamedArguments (ec)) {
+ if (!ResolveNamedArguments (rc)) {
return null;
}
- cb = new CustomAttributeBuilder (ctor, pos_values,
+ cb = new CustomAttributeBuilder (ctor_meta, pos_values,
prop_info_arr, prop_values_arr,
field_info_arr, field_values_arr);
return cb;
}
catch (Exception) {
- Error_AttributeArgumentNotValid (Location);
+ Error_AttributeArgumentNotValid (rc, Location);
return null;
}
}
- protected virtual ConstructorInfo ResolveConstructor (EmitContext ec)
+ protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
{
if (PosArguments != null) {
- for (int i = 0; i < PosArguments.Count; i++) {
- Argument a = (Argument) PosArguments [i];
-
- if (!a.Resolve (ec, Location))
- return null;
+ bool dynamic;
+ PosArguments.Resolve (ec, out dynamic);
+ if (dynamic) {
+ Error_AttributeArgumentNotValid (ec, loc);
+ return null;
}
}
-
- MethodGroupExpr mg = MemberLookupFinal (ec, ec.ContainerType,
+
+ MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
Type, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
Location) as MethodGroupExpr;
if (mg == null)
return null;
- ConstructorInfo constructor = (ConstructorInfo)mg;
+ var constructor = (MethodSpec) mg;
if (PosArguments == null) {
pos_values = EmptyObject;
return constructor;
}
- AParametersCollection pd = TypeManager.GetParameterData (constructor);
-
- int pos_arg_count = PosArguments.Count;
- pos_values = new object [pos_arg_count];
- for (int j = 0; j < pos_arg_count; ++j) {
- Argument a = (Argument) PosArguments [j];
-
- if (!a.Expr.GetAttributableValue (ec, a.Type, out pos_values [j]))
- return null;
- }
+ 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.
}
if (Type == pa.AttributeUsage && (int)pos_values [0] == 0) {
- Report.Error (591, Location, "Invalid value for argument to `System.AttributeUsage' attribute");
+ ec.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, ((Argument)PosArguments[0]).Expr.Location,
+ ec.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 &&
+ constructor.Parameters.Types [0] == TypeManager.short_type &&
!System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
Error_AttributeEmitError ("Incorrect argument value.");
return null;
return constructor;
}
- protected virtual bool ResolveNamedArguments (EmitContext ec)
+ protected virtual bool ResolveNamedArguments (ResolveContext ec)
{
int named_arg_count = NamedArguments.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);
+ var field_infos = new List<FieldInfo> (named_arg_count);
+ var prop_infos = new List<PropertyInfo> (named_arg_count);
+ var field_values = new List<object> (named_arg_count);
+ var prop_values = new List<object> (named_arg_count);
- ArrayList seen_names = new ArrayList(named_arg_count);
+ var seen_names = new List<string> (named_arg_count);
- foreach (DictionaryEntry de in NamedArguments) {
- string member_name = (string) de.Key;
-
- if (seen_names.Contains(member_name)) {
- Report.Error(643, Location, "'{0}' duplicate named attribute argument", member_name);
- return false;
- }
- seen_names.Add(member_name);
+ foreach (NamedArgument a in NamedArguments) {
+ string name = a.Name;
+ if (seen_names.Contains (name)) {
+ ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
+ continue;
+ }
+
+ seen_names.Add (name);
- Argument a = (Argument) de.Value;
- if (!a.Resolve (ec, Location))
- return false;
+ a.Resolve (ec);
- Expression member = Expression.MemberLookup (
- ec.ContainerType, Type, member_name,
- MemberTypes.Field | MemberTypes.Property,
- BindingFlags.Public | BindingFlags.Instance,
+ Expression member = Expression.MemberLookup (ec.Compiler,
+ ec.CurrentType, Type, name,
+ MemberTypes.All,
+ BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
Location);
if (member == null) {
- member = Expression.MemberLookup (ec.ContainerType, Type, member_name,
- MemberTypes.Field | MemberTypes.Property, BindingFlags.NonPublic | BindingFlags.Instance,
+ member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name,
+ MemberTypes.All, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
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, member_name);
+ Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
return false;
}
if (!(member is PropertyExpr || member is FieldExpr)) {
- Error_InvalidNamedArgument (member_name);
- return false;
- }
-
- if (a.Expr is TypeParameterExpr){
- Error_TypeParameterInAttribute (Location);
+ Error_InvalidNamedArgument (ec, a);
return false;
}
if (member is PropertyExpr) {
PropertyInfo pi = ((PropertyExpr) member).PropertyInfo;
- if (!pi.CanWrite || !pi.CanRead) {
- Report.SymbolRelatedToPreviousError (pi);
- Error_InvalidNamedArgument (member_name);
+ if (!pi.CanWrite || !pi.CanRead || pi.GetGetMethod ().IsStatic) {
+ ec.Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedArgument (ec, a);
return false;
}
if (!IsValidArgumentType (member.Type)) {
- Report.SymbolRelatedToPreviousError (pi);
- Error_InvalidNamedAgrumentType (member_name);
+ ec.Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedArgumentType (ec, a);
return false;
}
prop_infos.Add (pi);
} else {
- FieldInfo fi = ((FieldExpr) member).FieldInfo;
+ var fi = ((FieldExpr) member).Spec;
- if (fi.IsInitOnly) {
- Error_InvalidNamedArgument (member_name);
+ if (fi.IsReadOnly || fi.IsStatic) {
+ Error_InvalidNamedArgument (ec, a);
return false;
}
if (!IsValidArgumentType (member.Type)) {
- Report.SymbolRelatedToPreviousError (fi);
- Error_InvalidNamedAgrumentType (member_name);
+ ec.Report.SymbolRelatedToPreviousError (fi.MetaInfo);
+ Error_InvalidNamedArgumentType (ec, a);
return false;
}
if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
return false;
- FieldBase fb = TypeManager.GetField (fi);
+ FieldBase fb = TypeManager.GetField (fi.MetaInfo);
if (fb != null)
obsolete_attr = fb.GetObsoleteAttribute ();
else
- obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi);
+ obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi.MetaInfo);
- field_values.Add (value);
- field_infos.Add (fi);
+ field_values.Add (value);
+ field_infos.Add (fi.MetaInfo);
}
- if (obsolete_attr != null && !Owner.ResolveContext.IsInObsoleteScope)
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location);
+ if (obsolete_attr != null && !context.IsObsolete)
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
}
prop_info_arr = new PropertyInfo [prop_infos.Count];
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>
static AttributeUsageAttribute GetAttributeUsage (Type type)
{
- AttributeUsageAttribute ua = usage_attr_cache [type] as AttributeUsageAttribute;
- if (ua != null)
+ AttributeUsageAttribute ua;
+ if (usage_attr_cache.TryGetValue (type, out ua))
return ua;
Class attr_class = TypeManager.LookupClass (type);
}
// 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;
/// 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;
}
}
- 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
// 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 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)
return;
}
+ var predefined = PredefinedAttributes.Get;
+
try {
- foreach (Attributable owner in owners)
- owner.ApplyAttributeBuilder (this, cb, PredefinedAttributes.Get);
- }
- catch (Exception e) {
+ foreach (Attributable target in targets)
+ target.ApplyAttributeBuilder (this, cb, 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) {
- foreach (Argument arg in PosArguments) {
- // Type is undefined (was error 246)
- if (arg.Type == null)
- return;
-
- if (arg.Type.IsArray) {
- Report.Warning (3016, 1, Location, "Arrays as attribute arguments are not CLS-compliant");
- return;
- }
- }
- }
+ if (PosArguments != null)
+ PosArguments.CheckArrayAsAttribute (context.Compiler);
if (NamedArguments == null)
return;
-
- foreach (DictionaryEntry de in NamedArguments) {
- Argument arg = (Argument) de.Value;
-
- // Type is undefined (was error 246)
- if (arg.Type == null)
- return;
- if (arg.Type.IsArray) {
- Report.Warning (3016, 1, Location, "Arrays as attribute arguments are not CLS-compliant");
- return;
- }
- }
+ NamedArguments.CheckArrayAsAttribute (context.Compiler);
}
}
if (PosArguments == null || PosArguments.Count < 1)
return null;
- return ((Argument) PosArguments [0]).Expr;
+ return PosArguments [0].Expr;
}
public string GetString ()
return e.TypeArgument;
}
- public override Expression CreateExpressionTree (EmitContext ec)
+ public override Expression CreateExpressionTree (ResolveContext ec)
{
throw new NotSupportedException ("ET");
}
- public override Expression DoResolve (EmitContext ec)
+ protected override Expression DoResolve (ResolveContext ec)
{
throw new NotImplementedException ();
}
{
public readonly NamespaceEntry ns;
- public GlobalAttribute (NamespaceEntry ns, string target,
- Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped):
- base (target, left_expr, identifier, args, loc, nameEscaped)
+ public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
+ Arguments[] args, Location loc, bool nameEscaped):
+ base (target, expression, args, loc, nameEscaped)
{
this.ns = ns;
- this.owners = new Attributable[1];
}
- public override void AttachTo (Attributable owner)
+ public override void AttachTo (Attributable target, IMemberContext context)
{
if (ExplicitTarget == "assembly") {
- owners [0] = CodeGen.Assembly;
+ base.AttachTo (CodeGen.Assembly, context);
return;
}
+
if (ExplicitTarget == "module") {
- owners [0] = RootContext.ToplevelTypes;
+ base.AttachTo (RootContext.ToplevelTypes, context);
return;
}
+
throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
}
RootContext.ToplevelTypes.NamespaceEntry = null;
}
- protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent)
+ protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
{
try {
Enter ();
- return base.ResolveAsTypeTerminal (expr, ec, silent);
+ return base.ResolveAsTypeTerminal (expr, ec);
}
finally {
Leave ();
}
}
- protected override ConstructorInfo ResolveConstructor (EmitContext ec)
+ protected override MethodSpec ResolveConstructor (ResolveContext ec)
{
try {
Enter ();
}
}
- protected override bool ResolveNamedArguments (EmitContext ec)
+ protected override bool ResolveNamedArguments (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 void AttachTo (Attributable attributable)
+ public void AttachTo (Attributable attributable, IMemberContext context)
{
foreach (Attribute a in Attrs)
- a.AttachTo (attributable);
+ a.AttachTo (attributable, context);
}
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;
+
+ foreach (Attribute collision in d.Value)
+ a.Report.SymbolRelatedToPreviousError (collision.Location, "");
- Attribute a = (Attribute)d.Key;
- Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
+ a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
a.GetSignatureForError ());
}
}
/// </summary>
sealed class AttributeTester
{
- static PtrHashtable analyzed_types;
- static PtrHashtable analyzed_types_obsolete;
- static PtrHashtable analyzed_member_obsolete;
- static PtrHashtable analyzed_method_excluded;
- static PtrHashtable fixed_buffer_cache;
-
- static object TRUE = new object ();
- static object FALSE = new object ();
+ static Dictionary<Type, bool> analyzed_types;
+ static Dictionary<Type, ObsoleteAttribute> analyzed_types_obsolete;
+ static Dictionary<MemberInfo, ObsoleteAttribute> analyzed_member_obsolete;
+ static Dictionary<MethodBase, bool> analyzed_method_excluded;
+// static Dictionary<FieldInfo, IFixedBuffer> fixed_buffer_cache;
static AttributeTester ()
{
public static void Reset ()
{
- analyzed_types = new PtrHashtable ();
- analyzed_types_obsolete = new PtrHashtable ();
- analyzed_member_obsolete = new PtrHashtable ();
- analyzed_method_excluded = new PtrHashtable ();
- fixed_buffer_cache = new PtrHashtable ();
+ analyzed_types = new Dictionary<Type, bool> (ReferenceEquality<Type>.Default);
+ analyzed_types_obsolete = new Dictionary<Type, ObsoleteAttribute> (ReferenceEquality<Type>.Default);
+ analyzed_member_obsolete = new Dictionary<MemberInfo, ObsoleteAttribute> (ReferenceEquality<MemberInfo>.Default);
+ analyzed_method_excluded = new Dictionary<MethodBase, bool> (ReferenceEquality<MethodBase>.Default);
+// fixed_buffer_cache = new Dictionary<FieldInfo, IFixedBuffer> (ReferenceEquality<FieldInfo>.Default);
}
public enum Result {
if (type == null)
return true;
- object type_compliance = analyzed_types[type];
- if (type_compliance != null)
- return type_compliance == TRUE;
+ bool result;
+ if (analyzed_types.TryGetValue (type, out result))
+ return result;
if (type.IsPointer) {
- analyzed_types.Add (type, FALSE);
+ 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.GetTypeArguments (type) [0]);
+ result = IsClsCompliant (TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (type) [0]));
} else {
result = AnalyzeTypeCompliance (type);
}
- analyzed_types.Add (type, result ? TRUE : FALSE);
+ analyzed_types.Add (type, result);
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;
}
/// </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;
+ if (analyzed_types_obsolete.TryGetValue (type, out result))
+ return result;
- ObsoleteAttribute result = null;
if (TypeManager.HasElementType (type)) {
result = GetObsoleteAttribute (TypeManager.GetElementType (type));
} else if (TypeManager.IsGenericParameter (type))
}
// Cannot use .Add because of corlib bootstrap
- analyzed_types_obsolete [type] = result == null ? FALSE : result;
+ analyzed_types_obsolete [type] = result;
return result;
}
/// </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;
+ ObsoleteAttribute oa;
+ if (analyzed_member_obsolete.TryGetValue (mi, out oa))
+ return oa;
if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
return null;
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);
+ oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false) as ObsoleteAttribute;
+ analyzed_member_obsolete.Add (mi, 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);
public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
{
- object excluded = analyzed_method_excluded [mb];
- if (excluded != null)
- return excluded == TRUE ? true : false;
+ bool excluded;
+ if (analyzed_method_excluded.TryGetValue (mb, out excluded))
+ return excluded;
PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
if (!pa.IsDefined)
ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
as ConditionalAttribute[];
if (attrs.Length == 0) {
- analyzed_method_excluded.Add (mb, FALSE);
+ 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);
+ analyzed_method_excluded.Add (mb, false);
return false;
}
}
- analyzed_method_excluded.Add (mb, TRUE);
+ analyzed_method_excluded.Add (mb, true);
return true;
}
public readonly PredefinedAttribute CoClass;
public readonly PredefinedAttribute AttributeUsage;
public readonly PredefinedAttribute DefaultParameterValue;
+ public readonly PredefinedAttribute OptionalParameter;
// New in .NET 2.0
public readonly PredefinedAttribute DefaultCharset;
// New in .NET 3.5
public readonly PredefinedAttribute Extension;
+ // 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
//
CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
+ OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
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");
StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
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);
}
}
CustomAttributeBuilder cab;
ConstructorInfo ctor;
readonly string ns, name;
+ CompilerContext compiler;
+
+ static readonly Type NotFound = typeof (PredefinedAttribute);
public PredefinedAttribute (string ns, string name)
{
return base.GetHashCode ();
}
+ public string GetSignatureForError ()
+ {
+ return ns + "." + name;
+ }
+
public override bool Equals (object obj)
{
throw new NotSupportedException ();
builder.SetCustomAttribute (cab);
}
+ public void EmitAttribute (PropertyBuilder builder)
+ {
+ if (ResolveBuilder ())
+ builder.SetCustomAttribute (cab);
+ }
+
public void EmitAttribute (FieldBuilder builder)
{
if (ResolveBuilder ())
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;
}