2002-11-16 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / mcs / attribute.cs
index 125e64a77d5b6883906b3bbb7d6b020cf92e2be6..b939cf436ba46b09f46ef580e6a2f015cf3f41a5 100644 (file)
@@ -10,6 +10,7 @@
 //\r
 \r
 using System;\r
+using System.Diagnostics;\r
 using System.Collections;\r
 using System.Reflection;\r
 using System.Reflection.Emit;\r
@@ -110,6 +111,8 @@ namespace Mono.CSharp {
                {\r
                        if (Type == null)\r
                                Type = CheckAttributeType (ec);\r
+                       if (Type == null)\r
+                               return null;\r
 \r
                        bool MethodImplAttr = false;\r
                        bool MarshalAsAttr = false;\r
@@ -142,7 +145,7 @@ namespace Mono.CSharp {
                        //\r
                        // First process positional arguments \r
                        //\r
-                       \r
+\r
                        int i;\r
                        for (i = 0; i < pos_arg_count; i++) {\r
                                Argument a = (Argument) pos_args [i];\r
@@ -152,6 +155,7 @@ namespace Mono.CSharp {
                                        return null;\r
 \r
                                e = a.Expr;\r
+\r
                                if (e is Constant) {\r
                                        pos_values [i] = ((Constant) e).GetValue ();\r
                                } else if (e is TypeOf) {\r
@@ -222,7 +226,9 @@ namespace Mono.CSharp {
                                                                this.Inherited = (bool) o;\r
                                                }\r
                                                \r
-                                       } else { \r
+                                       } else if (e is TypeOf) {\r
+                                               prop_values.Add (((TypeOf) e).TypeArg);\r
+                                       } else {\r
                                                Error_AttributeArgumentNotValid ();\r
                                                return null;\r
                                        }\r
@@ -245,7 +251,9 @@ namespace Mono.CSharp {
                                                object value = ((Constant) e).GetValue ();\r
                                                \r
                                                field_values.Add (value);\r
-                                       } else { \r
+                                       } else if (e is TypeOf) {\r
+                                               field_values.Add (((TypeOf) e).TypeArg);\r
+                                       } else {\r
                                                Error_AttributeArgumentNotValid ();\r
                                                return null;\r
                                        }\r
@@ -270,6 +278,23 @@ namespace Mono.CSharp {
                                Error_AttributeConstructorMismatch (Location);\r
                                return null;\r
                        }\r
+\r
+                       //\r
+                       // Now we perform some checks on the positional args as they\r
+                       // cannot be null for a constructor which expects a parameter\r
+                       // of type object\r
+                       //\r
+\r
+                       ParameterData pd = Invocation.GetParameterData (constructor);\r
+\r
+                       for (int j = 0; j < pos_arg_count; ++j) {\r
+                               Argument a = (Argument) pos_args [j];\r
+                               \r
+                               if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) {\r
+                                       Error_AttributeArgumentNotValid ();\r
+                                       return null;\r
+                               }\r
+                       }\r
                        \r
                        PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count];\r
                        FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count];\r
@@ -287,6 +312,13 @@ namespace Mono.CSharp {
                                        (ConstructorInfo) constructor, pos_values,\r
                                        prop_info_arr, prop_values_arr,\r
                                        field_info_arr, field_values_arr); \r
+\r
+                       } catch (NullReferenceException) {\r
+                               // \r
+                               // Don't know what to do here\r
+                               //\r
+                               Report.Warning (\r
+                                       -100, Location, "NullReferenceException while trying to create attribute. Something's wrong!");\r
                        } catch {\r
                                //\r
                                // Sample:\r
@@ -325,8 +357,10 @@ namespace Mono.CSharp {
                                }\r
                                        \r
                                foreach (System.Attribute tmp in attrs)\r
-                                       if (tmp is AttributeUsageAttribute) \r
+                                       if (tmp is AttributeUsageAttribute) {\r
                                                targets = ((AttributeUsageAttribute) tmp).ValidOn;\r
+                                               break;\r
+                                       }\r
                        } else\r
                                targets = a.Targets;\r
 \r
@@ -442,7 +476,7 @@ namespace Mono.CSharp {
                                        return true;\r
                                else\r
                                        return false;\r
-                       } else if (element is Field) {\r
+                       } else if (element is Field || element is FieldBuilder) {\r
                                if ((targets & AttributeTargets.Field) != 0)\r
                                        return true;\r
                                else\r
@@ -452,7 +486,7 @@ namespace Mono.CSharp {
                                        return true;\r
                                else\r
                                        return false;\r
-                       } else if (element is Method || element is Operator || element is InterfaceMethod) {\r
+                       } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) {\r
                                if ((targets & AttributeTargets.Method) != 0)\r
                                        return true;\r
                                else\r
@@ -533,7 +567,73 @@ namespace Mono.CSharp {
                        }\r
                        return null;\r
                }\r
-               \r
+\r
+               //\r
+               // This pulls the condition name out of a Conditional attribute\r
+               //\r
+               public string Conditional_GetConditionName ()\r
+               {\r
+                       //\r
+                       // So we have a Conditional, pull the data out.\r
+                       //\r
+                       if (Arguments == null || Arguments [0] == null){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       ArrayList pos_args = (ArrayList) Arguments [0];\r
+                       if (pos_args.Count != 1){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       Argument arg = (Argument) pos_args [0]; \r
+                       if (!(arg.Expr is StringConstant)){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       return ((StringConstant) arg.Expr).Value;\r
+               }\r
+\r
+               //\r
+               // This pulls the obsolete message and error flag out of an Obsolete attribute\r
+               //\r
+               public string Obsolete_GetObsoleteMessage (out bool is_error)\r
+               {\r
+                       is_error = false;\r
+                       //\r
+                       // So we have an Obsolete, pull the data out.\r
+                       //\r
+                       if (Arguments == null || Arguments [0] == null)\r
+                               return "";\r
+\r
+                       ArrayList pos_args = (ArrayList) Arguments [0];\r
+                       if (pos_args.Count == 0)\r
+                               return "";\r
+                       else if (pos_args.Count > 2){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       Argument arg = (Argument) pos_args [0]; \r
+                       if (!(arg.Expr is StringConstant)){\r
+                               Error_AttributeConstructorMismatch (Location);\r
+                               return null;\r
+                       }\r
+\r
+                       if (pos_args.Count == 2){\r
+                               Argument arg2 = (Argument) pos_args [1];\r
+                               if (!(arg2.Expr is BoolConstant)){\r
+                                       Error_AttributeConstructorMismatch (Location);\r
+                                       return null;\r
+                               }\r
+                               is_error = ((BoolConstant) arg2.Expr).Value;\r
+                       }\r
+\r
+                       return ((StringConstant) arg.Expr).Value;\r
+               }\r
+\r
                //\r
                // Applies the attributes to the `builder'.\r
                //\r
@@ -564,16 +664,17 @@ namespace Mono.CSharp {
                                                        return;\r
                                                }\r
 \r
-                                       if (kind is Method || kind is Operator || kind is InterfaceMethod) {\r
-\r
+                                       if (kind is Method || kind is Operator || kind is InterfaceMethod ||\r
+                                           kind is Accessor) {\r
                                                if (a.Type == TypeManager.methodimpl_attr_type) {\r
                                                        if (a.ImplOptions == MethodImplOptions.InternalCall)\r
-                                                               ((MethodBuilder) builder).SetImplementationFlags (\r
-                                                                          MethodImplAttributes.InternalCall |\r
-                                                                          MethodImplAttributes.Runtime);\r
-                                               } else if (a.Type != TypeManager.dllimport_type)\r
+                                                               ((MethodBuilder) builder).\r
+                                                               SetImplementationFlags (\r
+                                                                       MethodImplAttributes.InternalCall |\r
+                                                                       MethodImplAttributes.Runtime);\r
+                                               } else if (a.Type != TypeManager.dllimport_type){\r
                                                        ((MethodBuilder) builder).SetCustomAttribute (cb);\r
-\r
+                                               }\r
                                        } else if (kind is Constructor) {\r
                                                ((ConstructorBuilder) builder).SetCustomAttribute (cb);\r
                                        } else if (kind is Field) {\r
@@ -631,10 +732,30 @@ namespace Mono.CSharp {
                                                "\tMicrosoft .NET runtime");\r
                                                }\r
                                                \r
+                                       } else if (kind is Interface) {\r
+                                               Interface iface = (Interface) kind;\r
+\r
+                                               if ((a.Type == TypeManager.default_member_type) &&\r
+                                                   (iface.InterfaceIndexers != null)) {\r
+                                                       Report.Error (\r
+                                                               646, loc,\r
+                                                               "Cannot specify the DefaultMember attribute on" +\r
+                                                               " a type containing an indexer");\r
+                                                       return;\r
+                                               }\r
+\r
+                                               if (!CheckAttribute (a, kind)) {\r
+                                                       Error_AttributeNotValidForElement (a, loc);\r
+                                                       return;\r
+                                               }\r
+\r
+                                               ((TypeBuilder) builder).SetCustomAttribute (cb);\r
                                        } else if (kind is AssemblyBuilder){\r
                                                ((AssemblyBuilder) builder).SetCustomAttribute (cb);\r
                                        } else if (kind is ModuleBuilder) {\r
                                                ((ModuleBuilder) builder).SetCustomAttribute (cb);\r
+                                       } else if (kind is FieldBuilder) {\r
+                                               ((FieldBuilder) builder).SetCustomAttribute (cb);\r
                                        } else\r
                                                throw new Exception ("Unknown kind: " + kind);\r
                                }\r
@@ -739,8 +860,11 @@ namespace Mono.CSharp {
                                }\r
                        }\r
 \r
+                       if (entry_point == null)\r
+                               entry_point = name;\r
+                       \r
                        MethodBuilder mb = builder.DefinePInvokeMethod (\r
-                               name, dll_name, flags | MethodAttributes.HideBySig,\r
+                               name, dll_name, entry_point, flags | MethodAttributes.HideBySig,\r
                                CallingConventions.Standard,\r
                                ret_type,\r
                                param_types,\r