//
-// attribute.cs: Attribute Handler
+// attribute.cs: Attributes handling
//
// Author: Ravi Pratap (ravi@ximian.com)
-// Marek Safar (marek.safar@seznam.cz)
+// Marek Safar (marek.safar@gmail.com)
//
// Dual licensed under the terms of the MIT X11 or GNU GPL
//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
-// Copyright 2011 Xamarin Inc
+// Copyright 2011-2013 Xamarin Inc
//
using System;
if (NamedArguments == null)
named_args = new Arguments (1);
- var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
+ var value = Constant.CreateConstantFromValue (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
}
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.
- /// </summary>
- public void Error_AttributeEmitError (string inner)
+ void Error_AttributeEmitError (string inner)
{
Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
- TypeManager.CSharpName (Type), inner);
+ Type.GetSignatureForError (), inner);
+ }
+
+ public void Error_InvalidArgumentValue (TypeSpec attributeType)
+ {
+ Report.Error (591, Location, "Invalid value for argument to `{0}' attribute", attributeType.GetSignatureForError ());
}
public void Error_InvalidSecurityParent ()
{
- Error_AttributeEmitError ("it is attached to invalid parent");
+ Report.Error (7070, Location,
+ "Security attribute `{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations",
+ Type.GetSignatureForError ());
}
Attributable Owner {
/// </summary>
void ResolveAttributeType (bool comparisonOnly)
{
- SessionReportPrinter resolve_printer = new SessionReportPrinter ();
+ var resolve_printer = new SessionReportPrinter ();
+ SessionReportPrinter secondary_printer = null;
ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
bool t1_is_attr = false;
try {
t1 = expression.ResolveAsType (context);
- if (t1 != null)
- t1_is_attr = t1.IsAttribute;
-
resolve_printer.EndSession ();
+ if (t1 != null && resolve_printer.ErrorsCount == 0)
+ t1_is_attr = t1.IsAttribute;
+
if (nameEscaped) {
t2 = null;
} else {
expanded = (ATypeNameExpression) expression.Clone (null);
expanded.Name += "Attribute";
+ secondary_printer = new SessionReportPrinter ();
+ Report.SetPrinter (secondary_printer);
t2 = expanded.ResolveAsType (context);
- if (t2 != null)
+ secondary_printer.EndSession ();
+ if (t2 != null && secondary_printer.ErrorsCount == 0)
t2_is_attr = t2.IsAttribute;
+
+ secondary_printer.EndSession ();
}
} finally {
context.Module.Compiler.Report.SetPrinter (prev_recorder);
resolve_error = true;
- if (t1 != null) {
- resolve_printer.Merge (prev_recorder);
+ if (t1 != null) {
+ if (resolve_printer.IsEmpty) {
+ Report.SymbolRelatedToPreviousError (t1);
+ Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
+ } else {
+ resolve_printer.Merge (prev_recorder);
+ }
- Report.SymbolRelatedToPreviousError (t1);
- Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
return;
}
if (t2 != null) {
- Report.SymbolRelatedToPreviousError (t2);
- Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+ if (secondary_printer.IsEmpty) {
+ Report.SymbolRelatedToPreviousError (t2);
+ Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+ } else {
+ secondary_printer.Merge (prev_recorder);
+ }
+
return;
}
public string GetSignatureForError ()
{
if (Type != null)
- return TypeManager.CSharpName (Type);
+ return Type.GetSignatureForError ();
return expression.GetSignatureForError ();
}
return HasSecurityAttribute && IsSecurityActionValid ();
}
- static bool IsValidArgumentType (TypeSpec t)
+ static bool IsValidMethodImplOption (int value)
+ {
+ //
+ // Allow to use AggressiveInlining on any runtime/corlib
+ //
+ MethodImplOptions all = (MethodImplOptions) 256;
+ foreach (MethodImplOptions v in System.Enum.GetValues (typeof (MethodImplOptions))) {
+ all |= v;
+ }
+
+ return ((MethodImplOptions) value | all) == all;
+ }
+
+ public static bool IsValidArgumentType (TypeSpec t)
{
if (t.IsArray) {
var ac = (ArrayContainer) t;
ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
if (obsolete_attr != null) {
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, Type.GetSignatureForError (), Location, Report);
}
ResolveContext rc = null;
{
SecurityAction action = GetSecurityActionValue ();
bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
+ var c = (Constant)pos_args [0].Expr;
switch (action) {
#pragma warning disable 618
#pragma warning restore 618
default:
- Error_AttributeEmitError ("SecurityAction is out of range");
+ Report.Error (7049, c.Location, "Security attribute `{0}' has an invalid SecurityAction value `{1}'",
+ Type.GetSignatureForError (), c.GetValueAsLiteral());
return false;
}
- Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
+ switch (Target) {
+ case AttributeTargets.Assembly:
+ Report.Error (7050, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to an assembly",
+ c.GetSignatureForError ());
+ break;
+ default:
+ Report.Error (7051, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to a type or a method",
+ c.GetSignatureForError ());
+ break;
+ }
+
return false;
}
return;
}
} else if (Type == predefined.Guid) {
+ string v = ((StringConstant) arg_expr).Value;
try {
- string v = ((StringConstant) arg_expr).Value;
new Guid (v);
- } catch (Exception e) {
- Error_AttributeEmitError (e.Message);
+ } catch {
+ Error_InvalidArgumentValue (Type);
return;
}
} else if (Type == predefined.AttributeUsage) {
int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
- if (v == 0) {
- context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
- "System.AttributeUsage");
- }
+ if (v == 0)
+ Error_InvalidArgumentValue (Type);
} else if (Type == predefined.MarshalAs) {
if (pos_args.Count == 1) {
var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
- Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
+ Report.Error (7055, pos_args [0].Expr.Location, "Unmanaged type `ByValArray' is only valid for fields");
}
}
} else if (Type == predefined.DllImport) {
if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
var value = ((Constant) pos_args[0].Expr).GetValue () as string;
if (string.IsNullOrEmpty (value))
- Error_AttributeEmitError ("DllName cannot be empty or null");
+ Error_InvalidArgumentValue (Type);
+ }
+ } else if (Type == predefined.MethodImpl) {
+ if (pos_args.Count == 1) {
+ var value = (int) ((Constant) arg_expr).GetValueAsLong ();
+
+ if (!IsValidMethodImplOption (value)) {
+ Error_InvalidArgumentValue (Type);
+ }
}
- } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
- !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
- Error_AttributeEmitError ("Incorrect argument value.");
- return;
}
}
- arg_expr.EncodeAttributeValue (context, encoder, pt);
+ arg_expr.EncodeAttributeValue (context, encoder, pt, pt);
}
}
encoder.Encode (na.Key.Type);
encoder.Encode (na.Value.Name);
- na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
+ na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type, na.Key.Type);
}
} else {
encoder.EncodeEmptyNamedArguments ();
cdata = encoder.ToArray ();
}
- try {
- foreach (Attributable target in targets)
- target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
- } catch (Exception e) {
- if (e is BadImageFormat && Report.Errors > 0)
- return;
+ if (!ctor.DeclaringType.IsConditionallyExcluded (context)) {
+ try {
+ foreach (Attributable target in targets)
+ target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
+ } catch (Exception e) {
+ if (e is BadImageFormat && Report.Errors > 0)
+ return;
- Error_AttributeEmitError (e.Message);
- return;
+ Error_AttributeEmitError (e.Message);
+ return;
+ }
}
if (!usage_attr.AllowMultiple && allEmitted != null) {
public Attributes (List<Attribute> attrs)
{
- Attrs = attrs;
+ Attrs = attrs ?? new List<Attribute> ();
}
public void AddAttribute (Attribute attr)
Encode ((byte) 0x54); // property
Encode (property.MemberType);
Encode (property.Name);
- value.EncodeAttributeValue (null, this, property.MemberType);
+ value.EncodeAttributeValue (null, this, property.MemberType, property.MemberType);
}
//
Encode ((byte) 0x53); // field
Encode (field.MemberType);
Encode (field.Name);
- value.EncodeAttributeValue (null, this, field.MemberType);
+ value.EncodeAttributeValue (null, this, field.MemberType, field.MemberType);
}
public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
Encode (member.MemberType);
Encode (member.Name);
- values [i].EncodeAttributeValue (null, this, member.MemberType);
+ values [i].EncodeAttributeValue (null, this, member.MemberType, member.MemberType);
}
}
public readonly PredefinedAttribute UnsafeValueType;
public readonly PredefinedAttribute UnmanagedFunctionPointer;
public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
+ public readonly PredefinedAttribute DebuggerStepThrough;
+ public readonly PredefinedDebuggableAttribute Debuggable;
// New in .NET 3.5
public readonly PredefinedAttribute Extension;
// New in .NET 4.5
public readonly PredefinedStateMachineAttribute AsyncStateMachine;
- public readonly PredefinedStateMachineAttribute IteratorStateMachine;
//
// Optional types which are used as types and for member lookup
public readonly PredefinedDecimalAttribute DecimalConstant;
public readonly PredefinedAttribute StructLayout;
public readonly PredefinedAttribute FieldOffset;
+ public readonly PredefinedAttribute AssemblyProduct;
+ public readonly PredefinedAttribute AssemblyCompany;
+ public readonly PredefinedAttribute AssemblyDescription;
+ public readonly PredefinedAttribute AssemblyCopyright;
+ public readonly PredefinedAttribute AssemblyTrademark;
public readonly PredefinedAttribute CallerMemberNameAttribute;
public readonly PredefinedAttribute CallerLineNumberAttribute;
public readonly PredefinedAttribute CallerFilePathAttribute;
UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
+ DebuggerStepThrough = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerStepThroughAttribute");
+ Debuggable = new PredefinedDebuggableAttribute (module, "System.Diagnostics", "DebuggableAttribute");
Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
+ AssemblyProduct = new PredefinedAttribute (module, "System.Reflection", "AssemblyProductAttribute");
+ AssemblyCompany = new PredefinedAttribute (module, "System.Reflection", "AssemblyCompanyAttribute");
+ AssemblyDescription = new PredefinedAttribute (module, "System.Reflection", "AssemblyDescriptionAttribute");
+ AssemblyCopyright = new PredefinedAttribute (module, "System.Reflection", "AssemblyCopyrightAttribute");
+ AssemblyTrademark = new PredefinedAttribute (module, "System.Reflection", "AssemblyTrademarkAttribute");
AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
- IteratorStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "IteratorStateMachineAttribute") {
- IsIterator = true
- };
CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
//
// Handle all parameter-less attributes as optional
//
- if (!IsDefined)
+ if (!Define ())
return false;
ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
}
}
+ public class PredefinedDebuggableAttribute : PredefinedAttribute
+ {
+ public PredefinedDebuggableAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
+ }
+
+ public void EmitAttribute (AssemblyBuilder builder, System.Diagnostics.DebuggableAttribute.DebuggingModes modes)
+ {
+ var atype = module.PredefinedAttributes.Debuggable;
+ if (!atype.Define ())
+ return;
+
+ MethodSpec ctor = null;
+ foreach (MethodSpec m in MemberCache.FindMembers (atype.TypeSpec, CSharp.Constructor.ConstructorName, true)) {
+ if (m.Parameters.Count != 1)
+ continue;
+
+ if (m.Parameters.Types[0].Kind == MemberKind.Enum) {
+ ctor = m;
+ }
+ }
+
+ if (ctor == null)
+ return;
+
+ AttributeEncoder encoder = new AttributeEncoder ();
+ encoder.Encode ((int) modes);
+ encoder.EncodeEmptyNamedArguments ();
+
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ }
+ }
+
public class PredefinedDecimalAttribute : PredefinedAttribute
{
public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
{
}
- public bool IsIterator { get; set; }
-
public void EmitAttribute (MethodBuilder builder, StateMachine type)
{
- var predefined_ctor = IsIterator ?
- module.PredefinedMembers.IteratorStateMachineAttributeCtor :
- module.PredefinedMembers.AsyncStateMachineAttributeCtor;
+ var predefined_ctor = module.PredefinedMembers.AsyncStateMachineAttributeCtor;
var ctor = predefined_ctor.Get ();
if (ac != null) {
element = GetTransformationFlags (ac.Element);
if (element == null)
- return null;
+ return new bool[] { false, false };
bool[] res = new bool[element.Length + 1];
res[0] = false;