X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fdecl.cs;h=4f16835d2dad207999d2bd100439289c27ffabd3;hb=a4c049eb2217fb63d763181b7a1280b2190ebe31;hp=c5528244717c9350eb0eebb57902023406a8fa92;hpb=86f7e3d6c9ade69754c8da33621128b11140ee07;p=mono.git
diff --git a/mcs/mcs/decl.cs b/mcs/mcs/decl.cs
index c5528244717..4f16835d2da 100644
--- a/mcs/mcs/decl.cs
+++ b/mcs/mcs/decl.cs
@@ -29,24 +29,56 @@ namespace Mono.CSharp {
public class MemberName {
public readonly string Name;
public readonly MemberName Left;
+ public readonly Location Location;
+
+ bool is_double_colon;
public static readonly MemberName Null = new MemberName ("");
- public MemberName (string name)
+ private MemberName (MemberName left, string name, bool is_double_colon, Location loc)
{
this.Name = name;
+ this.Location = loc;
+ this.is_double_colon = is_double_colon;
+ this.Left = left;
+ }
+
+ public MemberName (string name)
+ : this (null, name, false, Location.Null)
+ {
}
public MemberName (MemberName left, string name)
- : this (name)
+ : this (left, name, false, left != null ? left.Location : Location.Null)
+ {
+ }
+
+ public MemberName (string name, Location loc)
+ : this (null, name, false, loc)
+ {
+ }
+
+ public MemberName (MemberName left, string name, Location loc)
+ : this (left, name, false, loc)
+ {
+ }
+
+ public MemberName (string alias, string name, Location loc)
+ : this (new MemberName (alias), name, true, loc)
{
- this.Left = left;
}
public MemberName (MemberName left, MemberName right)
+ : this (left, right, right.Location)
{
- Name = right.Name;
- Left = (right.Left == null) ? left : new MemberName (left, right.Left);
+ }
+
+ public MemberName (MemberName left, MemberName right, Location loc)
+ : this (null, right.Name, false, loc)
+ {
+ if (right.is_double_colon)
+ throw new InternalErrorException ("Cannot append double_colon member name");
+ this.Left = (right.Left == null) ? left : new MemberName (left, right.Left);
}
static readonly char [] dot_array = { '.' };
@@ -70,8 +102,9 @@ namespace Mono.CSharp {
public string GetName (bool is_generic)
{
string name = is_generic ? Basename : Name;
+ string connect = is_double_colon ? "::" : ".";
if (Left != null)
- return Left.GetName (is_generic) + "." + name;
+ return Left.GetName (is_generic) + connect + name;
else
return name;
}
@@ -82,49 +115,51 @@ namespace Mono.CSharp {
///
public string GetPartialName ()
{
+ string connect = is_double_colon ? "::" : ".";
if (Left != null)
- return Left.GetPartialName () + "." + Name;
+ return Left.GetPartialName () + connect + Name;
else
return Name;
}
public string GetTypeName ()
{
+ string connect = is_double_colon ? "::" : ".";
if (Left != null)
- return Left.GetTypeName () + "." + Name;
+ return Left.GetTypeName () + connect + Name;
else
return Name;
}
- public Expression GetTypeExpression (Location loc)
+ public Expression GetTypeExpression ()
{
- if (Left != null) {
- Expression lexpr = Left.GetTypeExpression (loc);
-
- return new MemberAccess (lexpr, Name, loc);
- } else {
- return new SimpleName (Name, loc);
+ if (Left == null)
+ return new SimpleName (Name, Location);
+ if (is_double_colon) {
+ if (Left.Left != null)
+ throw new InternalErrorException ("The left side of a :: should be an identifier");
+ return new QualifiedAliasMember (Left.Name, Name, Location);
}
+
+ Expression lexpr = Left.GetTypeExpression ();
+ return new MemberAccess (lexpr, Name, Location);
}
public MemberName Clone ()
{
- if (Left != null)
- return new MemberName (Left.Clone (), Name);
- else
- return new MemberName (Name);
+ MemberName left_clone = Left == null ? null : Left.Clone ();
+ return new MemberName (left_clone, Name, is_double_colon, Location);
}
public string Basename {
- get {
- return Name;
- }
+ get { return Name; }
}
public override string ToString ()
{
+ string connect = is_double_colon ? "::" : ".";
if (Left != null)
- return Left + "." + Name;
+ return Left + connect + Name;
else
return Name;
}
@@ -140,6 +175,8 @@ namespace Mono.CSharp {
return true;
if (other == null || Name != other.Name)
return false;
+ if (is_double_colon != other.is_double_colon)
+ return false;
#if NET_2_0
if (TypeArguments == null)
return other.TypeArguments == null;
@@ -158,7 +195,8 @@ namespace Mono.CSharp {
int hash = Name.GetHashCode ();
for (MemberName n = Left; n != null; n = n.Left)
hash ^= n.Name.GetHashCode ();
-
+ if (is_double_colon)
+ hash ^= 0xbadc01d;
#if NET_2_0
if (TypeArguments != null)
hash ^= TypeArguments.Count << 5;
@@ -202,7 +240,9 @@ namespace Mono.CSharp {
///
/// Location where this declaration happens
///
- public readonly Location Location;
+ public Location Location {
+ get { return member_name.Location; }
+ }
///
/// XML documentation comment
@@ -228,7 +268,8 @@ namespace Mono.CSharp {
Excluded_Undetected = 1 << 8, // Conditional attribute has not been detected yet
Excluded = 1 << 9, // Method is conditional
TestMethodDuplication = 1 << 10, // Test for duplication must be performed
- IsUsed = 1 << 11
+ IsUsed = 1 << 11,
+ IsAssigned = 1 << 12 // Field is assigned
}
///
@@ -236,8 +277,7 @@ namespace Mono.CSharp {
///
internal Flags caching_flags;
- public MemberCore (TypeContainer parent, MemberName name, Attributes attrs,
- Location loc)
+ public MemberCore (TypeContainer parent, MemberName name, Attributes attrs)
: base (attrs)
{
if (parent is PartialContainer && !(this is PartialContainer))
@@ -245,7 +285,6 @@ namespace Mono.CSharp {
Parent = parent;
member_name = name;
- Location = loc;
caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected;
}
@@ -255,21 +294,6 @@ namespace Mono.CSharp {
cached_name = null;
}
- ///
- /// Tests presence of ObsoleteAttribute and report proper error
- ///
- protected void CheckUsageOfObsoleteAttribute (Type type)
- {
- if (type == null)
- return;
-
- ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type);
- if (obsolete_attr == null)
- return;
-
- AttributeTester.Report_ObsoleteMessage (obsolete_attr, type.FullName, Location);
- }
-
public abstract bool Define ();
//
@@ -277,15 +301,10 @@ namespace Mono.CSharp {
//
public virtual string GetSignatureForError ()
{
- return Name;
- }
+ if (Parent == null || Parent.Parent == null)
+ return Name;
- ///
- /// Use this method when MethodBuilder is null
- ///
- public virtual string GetSignatureForError (TypeContainer tc)
- {
- return Name;
+ return String.Concat (Parent.GetSignatureForError (), '.', Name);
}
///
@@ -293,16 +312,19 @@ namespace Mono.CSharp {
///
public virtual void Emit ()
{
- // Hack with Parent == null is for EnumMember
- if (Parent == null || (GetObsoleteAttribute (Parent) == null && Parent.GetObsoleteAttribute (Parent) == null))
- VerifyObsoleteAttribute ();
-
if (!RootContext.VerifyClsCompliance)
return;
VerifyClsCompliance (Parent);
}
+ public virtual EmitContext EmitContext
+ {
+ get {
+ return Parent.EmitContext;
+ }
+ }
+
public bool InUnsafe {
get {
return ((ModFlags & Modifiers.UNSAFE) != 0) || Parent.UnsafeContext;
@@ -341,7 +363,7 @@ namespace Mono.CSharp {
///
/// Returns instance of ObsoleteAttribute for this MemberCore
///
- public ObsoleteAttribute GetObsoleteAttribute (DeclSpace ds)
+ public virtual ObsoleteAttribute GetObsoleteAttribute ()
{
// ((flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) is slower, but why ?
if ((caching_flags & Flags.Obsolete_Undetected) == 0 && (caching_flags & Flags.Obsolete) == 0) {
@@ -354,11 +376,11 @@ namespace Mono.CSharp {
return null;
Attribute obsolete_attr = OptAttributes.Search (
- TypeManager.obsolete_attribute_type, ds.EmitContext);
+ TypeManager.obsolete_attribute_type, EmitContext);
if (obsolete_attr == null)
return null;
- ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (ds.EmitContext);
+ ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (EmitContext);
if (obsolete == null)
return null;
@@ -366,6 +388,34 @@ namespace Mono.CSharp {
return obsolete;
}
+ ///
+ /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements
+ ///
+ public virtual void CheckObsoleteness (Location loc)
+ {
+ if (Parent != null)
+ Parent.CheckObsoleteness (loc);
+
+ ObsoleteAttribute oa = GetObsoleteAttribute ();
+ if (oa == null) {
+ return;
+ }
+
+ AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc);
+ }
+
+ protected void CheckObsoleteType (Expression type)
+ {
+ ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (type.Type);
+ if (obsolete_attr == null)
+ return;
+
+ if (GetObsoleteAttribute () != null || Parent.GetObsoleteAttribute () != null)
+ return;
+
+ AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (type.Type), type.Location);
+ }
+
///
/// Analyze whether CLS-Compliant verification must be execute for this MemberCore.
///
@@ -445,29 +495,28 @@ namespace Mono.CSharp {
if (!IsClsCompliaceRequired (ds)) {
if (HasClsCompliantAttribute && RootContext.WarningLevel >= 2) {
if (!IsExposedFromAssembly (ds))
- Report.Warning (3019, Location, "CLS compliance checking will not be performed on '{0}' because it is private or internal", GetSignatureForError ());
+ Report.Warning (3019, Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ());
if (!CodeGen.Assembly.IsClsCompliant)
- Report.Warning (3021, Location, "'{0}' does not need a CLSCompliant attribute because the assembly does not have a CLSCompliant attribute", GetSignatureForError ());
+ Report.Warning (3021, Location, "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", GetSignatureForError ());
}
return false;
}
if (!CodeGen.Assembly.IsClsCompliant) {
if (HasClsCompliantAttribute) {
- Report.Error (3014, Location, "'{0}' cannot be marked as CLS-compliant because the assembly does not have a CLSCompliant attribute", GetSignatureForError ());
+ Report.Error (3014, Location,
+ "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant",
+ GetSignatureForError ());
}
return false;
}
- int index = Name.LastIndexOf ('.');
- if (Name [index > 0 ? index + 1 : 0] == '_') {
- Report.Error (3008, Location, "Identifier '{0}' is not CLS-compliant", GetSignatureForError () );
+ if (member_name.Name [0] == '_') {
+ Report.Error (3008, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () );
}
return true;
}
- protected abstract void VerifyObsoleteAttribute ();
-
//
// Raised (and passed an XmlElement that contains the comment)
// when GenerateDocComment is writing documentation expectedly.
@@ -506,7 +555,7 @@ namespace Mono.CSharp {
/// provides the common foundation for managing those name
/// spaces.
///
- public abstract class DeclSpace : MemberCore, IAlias {
+ public abstract class DeclSpace : MemberCore {
///
/// This points to the actual definition that is being
/// created with System.Reflection.Emit
@@ -528,15 +577,17 @@ namespace Mono.CSharp {
// The emit context for toplevel objects.
protected EmitContext ec;
- public EmitContext EmitContext {
- get { return ec; }
+ public override EmitContext EmitContext {
+ get {
+ return ec;
+ }
}
static string[] attribute_targets = new string [] { "type" };
public DeclSpace (NamespaceEntry ns, TypeContainer parent, MemberName name,
- Attributes attrs, Location l)
- : base (parent, name, attrs, l)
+ Attributes attrs)
+ : base (parent, name, attrs)
{
NamespaceEntry = ns;
Basename = name.Name;
@@ -550,7 +601,7 @@ namespace Mono.CSharp {
{
if (name == Basename && !(this is Interface) && !(this is Enum)) {
Report.SymbolRelatedToPreviousError (this);
- Report.Error (542, symbol.Location, "'{0}': member names cannot be the same as their enclosing type", symbol.GetSignatureForError ());
+ Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type", symbol.GetSignatureForError ());
return false;
}
@@ -565,14 +616,22 @@ namespace Mono.CSharp {
return true;
Report.SymbolRelatedToPreviousError (mc);
- Report.Error (102, symbol.Location, "The type '{0}' already contains a definition for '{1}'", GetSignatureForError (), name);
- return false;
- }
+ if (symbol is PartialContainer || mc is PartialContainer) {
+ Report.Error (260, symbol.Location,
+ "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
+ name);
+ return false;
+ }
- public void RecordDecl ()
- {
- if ((NamespaceEntry != null) && (Parent == RootContext.Tree.Types))
- NamespaceEntry.DefineName (MemberName.Basename, this);
+ if (this is RootTypes) {
+ Report.Error (101, symbol.Location,
+ "The namespace `{0}' already contains a definition for `{1}'",
+ ((DeclSpace)symbol).NamespaceEntry.GetSignatureForError (), symbol.MemberName.Name);
+ } else {
+ Report.Error (102, symbol.Location, "The type `{0}' already contains a definition for `{1}'",
+ GetSignatureForError (), symbol.MemberName.Name);
+ }
+ return false;
}
///
@@ -591,13 +650,7 @@ namespace Mono.CSharp {
// why there is a non-obvious test down here.
//
public bool IsTopLevel {
- get {
- if (Parent != null){
- if (Parent.Parent == null)
- return true;
- }
- return false;
- }
+ get { return (Parent != null && Parent.Parent == null); }
}
public virtual void CloseType ()
@@ -622,9 +675,7 @@ namespace Mono.CSharp {
}
protected virtual TypeAttributes TypeAttr {
- get {
- return CodeGen.Module.DefaultCharSetType;
- }
+ get { return CodeGen.Module.DefaultCharSetType; }
}
///
@@ -636,7 +687,20 @@ namespace Mono.CSharp {
/// Define all members, but don't apply any attributes or do anything which may
/// access not-yet-defined classes. This method also creates the MemberCache.
///
- public abstract bool DefineMembers (TypeContainer parent);
+ public virtual bool DefineMembers (TypeContainer parent)
+ {
+ if (((ModFlags & Modifiers.NEW) != 0) && IsTopLevel) {
+ Report.Error (1530, Location, "Keyword `new' is not allowed on namespace elements");
+ return false;
+ }
+ return true;
+ }
+
+ public override string GetSignatureForError ()
+ {
+ // Parent.GetSignatureForError
+ return Name;
+ }
//
// Whether this is an `unsafe context'
@@ -747,11 +811,7 @@ namespace Mono.CSharp {
protected bool FamilyAccessible (Type check_type)
{
Type declaring = check_type.DeclaringType;
- if (TypeBuilder == declaring ||
- TypeBuilder.IsSubclassOf (declaring))
- return true;
-
- return NestedAccessible (check_type);
+ return TypeManager.IsNestedFamilyAccessible (TypeBuilder, declaring);
}
// Access level of a type.
@@ -855,13 +915,6 @@ namespace Mono.CSharp {
return ~ (~ mAccess | pAccess) == 0;
}
- public static void Error_AmbiguousTypeReference (Location loc, string name, string t1, string t2)
- {
- Report.Error (104, loc,
- "`{0}' is an ambiguous reference ({1} or {2})",
- name, t1, t2);
- }
-
//
// Return the nested type with name @name. Ensures that the nested type
// is defined if necessary. Do _not_ use this when you have a MemberCache handy.
@@ -900,8 +953,7 @@ namespace Mono.CSharp {
}
//
- // Public function used to locate types, this can only
- // be used after the ResolveTree function has been invoked.
+ // Public function used to locate types.
//
// Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
//
@@ -992,25 +1044,37 @@ namespace Mono.CSharp {
}
public override string[] ValidAttributeTargets {
- get {
- return attribute_targets;
- }
+ get { return attribute_targets; }
}
- bool IAlias.IsType {
- get { return true; }
- }
+ protected override bool VerifyClsCompliance (DeclSpace ds)
+ {
+ if (!base.VerifyClsCompliance (ds)) {
+ return false;
+ }
- string IAlias.Name {
- get { return Name; }
- }
+ IDictionary cache = TypeManager.AllClsTopLevelTypes;
+ string lcase = Name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
+ if (!cache.Contains (lcase)) {
+ cache.Add (lcase, this);
+ return true;
+ }
- TypeExpr IAlias.ResolveAsType (EmitContext ec)
- {
- if (TypeBuilder == null)
- throw new InvalidOperationException ();
+ object val = cache [lcase];
+ if (val == null) {
+ Type t = AttributeTester.GetImportedIgnoreCaseClsType (lcase);
+ if (t == null)
+ return true;
+ Report.SymbolRelatedToPreviousError (t);
+ }
+ else {
+ if (val is PartialContainer)
+ return true;
- return new TypeExpression (TypeBuilder, Location);
+ Report.SymbolRelatedToPreviousError ((DeclSpace)val);
+ }
+ Report.Error (3005, Location, "Identifier `{0}' differing only in case is not CLS-compliant", GetSignatureForError ());
+ return true;
}
}
@@ -1399,17 +1463,10 @@ namespace Mono.CSharp {
AddMethods (BindingFlags.Instance | BindingFlags.NonPublic, type);
}
+ static ArrayList overrides = new ArrayList ();
+
void AddMethods (BindingFlags bf, Type type)
{
- //
- // Consider the case:
- //
- // class X { public virtual int f() {} }
- // class Y : X {}
- //
- // When processing 'Y', the method_cache will already have a copy of 'f',
- // with ReflectedType == X. However, we want to ensure that its ReflectedType == Y
- //
MethodBase [] members = type.GetMethods (bf);
Array.Reverse (members);
@@ -1428,33 +1485,21 @@ namespace Mono.CSharp {
while (curr.IsVirtual && (curr.Attributes & MethodAttributes.NewSlot) == 0) {
MethodInfo base_method = curr.GetBaseDefinition ();
- if (base_method == curr) {
- //
- // Both mcs and CSC 1.1 seem to emit a somewhat broken
- // ...Invoke () function for delegates: it's missing a 'newslot'.
- // CSC 2.0 emits a 'newslot' for a delegate's Invoke.
- //
- // Also, CSC 1.1 appears to emit 'Finalize' without a newslot.
- //
- if ((member.Name != "Invoke" ||
- !type.IsSubclassOf (TypeManager.multicast_delegate_type)) &&
- (member.Name != "Finalize" ||
- type != TypeManager.object_type)) {
- Report.SymbolRelatedToPreviousError (base_method);
- Report.Warning (-28,
- "The method '{0}' is marked 'override'," +
- " but doesn't appear to override any virtual or abstract method:" +
- " it may be ignored during overload resolution",
- TypeManager.CSharpSignature (base_method));
- }
-
+ if (base_method == curr)
+ // Not every virtual function needs to have a NewSlot flag.
break;
- }
-
+
+ overrides.Add (curr);
list.Add (new CacheEntry (null, base_method, MemberTypes.Method, bf));
curr = base_method;
}
+ if (overrides.Count > 0) {
+ for (int i = 0; i < overrides.Count; ++i)
+ TypeManager.RegisterOverride ((MethodBase) overrides [i], curr);
+ overrides.Clear ();
+ }
+
// Unfortunately, the elements returned by Type.GetMethods() aren't
// sorted so we need to do this check for every member.
BindingFlags new_bf = bf;
@@ -1986,7 +2031,10 @@ namespace Mono.CSharp {
continue;
MethodBase method_to_compare = (MethodBase)entry.Member;
- if (AttributeTester.AreOverloadedMethodParamsClsCompliant (method.ParameterTypes, TypeManager.GetArgumentTypes (method_to_compare)))
+ AttributeTester.Result result = AttributeTester.AreOverloadedMethodParamsClsCompliant (
+ method.ParameterTypes, TypeManager.GetArgumentTypes (method_to_compare));
+
+ if (result == AttributeTester.Result.Ok)
continue;
IMethodData md = TypeManager.GetMethod (method_to_compare);
@@ -1997,7 +2045,16 @@ namespace Mono.CSharp {
continue;
Report.SymbolRelatedToPreviousError (entry.Member);
- Report.Error (3006, method.Location, "Overloaded method '{0}' differing only in ref or out, or in array rank, is not CLS-compliant", method.GetSignatureForError ());
+ switch (result) {
+ case AttributeTester.Result.RefOutArrayError:
+ Report.Error (3006, method.Location, "Overloaded method `{0}' differing only in ref or out, or in array rank, is not CLS-compliant", method.GetSignatureForError ());
+ continue;
+ case AttributeTester.Result.ArrayArrayError:
+ Report.Error (3007, method.Location, "Overloaded method `{0}' differing only by unnamed array types is not CLS-compliant", method.GetSignatureForError ());
+ continue;
+ }
+
+ throw new NotImplementedException (result.ToString ());
}
}
}