Author: martin
Date: 2005-03-21 13:11:45 -0500 (Mon, 21 Mar 2005)
New Revision: 42051
Modified:
trunk/mcs/gmcs/ChangeLog
trunk/mcs/gmcs/class.cs
trunk/mcs/gmcs/const.cs
trunk/mcs/gmcs/cs-parser.jay
trunk/mcs/gmcs/namespace.cs
Log:
**** Merged r39917-r39971 from MCS ****
Modified: trunk/mcs/gmcs/ChangeLog
===================================================================
--- trunk/mcs/gmcs/ChangeLog 2005-03-21 17:10:19 UTC (rev 42050)
+++ trunk/mcs/gmcs/ChangeLog 2005-03-21 18:11:45 UTC (rev 42051)
@@ -1,3 +1,58 @@
+2005-02-02 Raja R Harinath <[EMAIL PROTECTED]>
+
+ Fix a crasher in a variant of #31984.
+ * const.cs (Constant.CheckBase): New override that defers the
+ new-or-override check in case the base type hasn't been populated
+ yet.
+ (Constant.Define): Ensure the new-or-override check is performed.
+
+2005-02-01 Duncan Mak <[EMAIL PROTECTED]>
+
+ * const.cs (LookupConstantValue): Check that `ce' is not null
+ before calling GetValue ().
+
+2005-02-01 Raja R Harinath <[EMAIL PROTECTED]>
+
+ Fix test-334.cs (#69519).
+ * cs-parser.jay (using_alias_directive): Pass in an expression to
+ NamespaceEntry.UsingAlias.
+ (using_namespace_directive): Pass in an expression to
+ NamespaceEntry.Using.
+ (namespace_name): Don't flatten to a string.
+ * namespace.cs (NamespaceEntry.AliasEntry): Store an expression.
+ (NamespaceEntry.AliasEntry.Resolve): Lookup using
+ ResolveAsTypeStep.
+ (NamespaceEntry.UsingEntry): Likewise.
+ (NamespaceEntry.Using,NamespaceEntry.UsingAlias): Update to
+ changes.
+ (NamespaceEntry.LookupForUsing): Remove.
+ (NamespaceEntry.LookupNamespaceOrType): Add support for dotted
+ names.
+ (NamespaceEntry.Lookup): Remove support for dotted names.
+
+2005-02-01 Raja R Harinath <[EMAIL PROTECTED]>
+
+ * namespace.cs (NamespaceEntry.NamespaceEntry): Simplify, and
+ split into two.
+ (NamespaceEntry.ImplicitParent): Compute on demand.
+ (NamespaceEntry.Doppelganger): New implicit namespace-entry that
+ parallels the current.
+ (NamespaceEntry.LookupForUsing): Use it.
+ (NamespaceEntry.Lookup): If the current namespace-entry is
+ implicit, don't search aliases and using tables.
+
+2005-02-01 Raja R Harinath <[EMAIL PROTECTED]>
+
+ Fix #31984.
+ * class.cs (TypeContainer.DoDefineMembers): Don't initialize
+ BaseCache here.
+ (TypeContainer.BaseCache): Compute on demand.
+ (TypeContainer.FindMembers): Define constants and types if they're
+ not already created.
+ (FieldMember.Define): Move resetting of ec.InUnsafe before error
+ check.
+ * const.cs (Constant.Define): Make idempotent.
+
2005-01-29 Miguel de Icaza <[EMAIL PROTECTED]>
* pending.cs: Produce better code (no nops produced by using Ldarg
Modified: trunk/mcs/gmcs/class.cs
===================================================================
--- trunk/mcs/gmcs/class.cs 2005-03-21 17:10:19 UTC (rev 42050)
+++ trunk/mcs/gmcs/class.cs 2005-03-21 18:11:45 UTC (rev 42051)
@@ -1470,15 +1470,6 @@
protected virtual bool DoDefineMembers ()
{
- //
- // We need to be able to use the member cache while we
are checking/defining
- //
- if (TypeBuilder.BaseType != null)
- base_cache = TypeManager.LookupMemberCache
(TypeBuilder.BaseType);
-
- if (TypeBuilder.IsInterface)
- base_cache =
TypeManager.LookupBaseInterfacesCache (TypeBuilder);
-
if (IsTopLevel) {
if ((ModFlags & Modifiers.NEW) != 0)
Error_KeywordNotAllowed (Location);
@@ -1799,6 +1790,10 @@
continue;
FieldBuilder fb =
con.FieldBuilder;
+ if (fb == null) {
+ if (con.Define ())
+ fb =
con.FieldBuilder;
+ }
if (fb != null && filter (fb,
criteria) == true) {
if (members == null)
members = new
ArrayList ();
@@ -1986,6 +1981,9 @@
continue;
TypeBuilder tb = t.TypeBuilder;
+ if (tb == null)
+ tb = t.DefineType ();
+
if (tb != null && (filter (tb,
criteria) == true)) {
if (members == null)
members = new
ArrayList ();
@@ -2588,6 +2586,12 @@
public virtual MemberCache BaseCache {
get {
+ if (base_cache != null)
+ return base_cache;
+ if (TypeBuilder.BaseType != null)
+ base_cache =
TypeManager.LookupMemberCache (TypeBuilder.BaseType);
+ if (TypeBuilder.IsInterface)
+ base_cache =
TypeManager.LookupBaseInterfacesCache (TypeBuilder);
return base_cache;
}
}
@@ -5661,9 +5665,9 @@
}
if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE))
== 0) {
- Report.SymbolRelatedToPreviousError
(conflict_symbol);
- Report.Warning (108, Location, "The keyword new
is required on '{0}' because it hides inherited member", GetSignatureForError
(Parent));
- }
+ Report.SymbolRelatedToPreviousError
(conflict_symbol);
+ Report.Warning (108, Location, "The keyword new
is required on '{0}' because it hides inherited member", GetSignatureForError
(Parent));
+ }
return true;
}
@@ -5762,13 +5766,13 @@
MemberType = texpr.Type;
+ ec.InUnsafe = old_unsafe;
+
if (MemberType == TypeManager.void_type) {
Report.Error (1547, Location, "Keyword 'void'
cannot be used in this context");
return false;
}
- ec.InUnsafe = old_unsafe;
-
if (!CheckBase ())
return false;
Modified: trunk/mcs/gmcs/const.cs
===================================================================
--- trunk/mcs/gmcs/const.cs 2005-03-21 17:10:19 UTC (rev 42050)
+++ trunk/mcs/gmcs/const.cs 2005-03-21 18:11:45 UTC (rev 42051)
@@ -62,11 +62,25 @@
}
#endif
+ protected override bool CheckBase ()
+ {
+ // Constant.Define can be called when the parent type
hasn't yet been populated
+ // and it's base types need not have been populated.
So, we defer this check
+ // to the second time Define () is called on this
member.
+ if (Parent.BaseCache == null)
+ return true;
+ return base.CheckBase ();
+ }
+
/// <summary>
/// Defines the constant in the @parent
/// </summary>
public override bool Define ()
{
+ // Make Define () idempotent, but ensure that the error
check happens.
+ if (FieldBuilder != null)
+ return base.CheckBase ();
+
if (!base.Define ())
return false;
@@ -248,8 +262,10 @@
}
Expr = ce;
}
- ConstantValue = ce.GetValue ();
+ if (ce != null)
+ ConstantValue = ce.GetValue ();
+
if (MemberType.IsEnum){
//
// This sadly does not work for our
user-defined enumerations types ;-(
Modified: trunk/mcs/gmcs/cs-parser.jay
===================================================================
--- trunk/mcs/gmcs/cs-parser.jay 2005-03-21 17:10:19 UTC (rev 42050)
+++ trunk/mcs/gmcs/cs-parser.jay 2005-03-21 18:11:45 UTC (rev 42051)
@@ -338,7 +338,8 @@
: USING IDENTIFIER ASSIGN
namespace_or_type_name SEMICOLON
{
- current_namespace.UsingAlias ((string) $2, (MemberName) $4,
lexer.Location);
+ MemberName name = (MemberName) $4;
+ current_namespace.UsingAlias ((string) $2,
name.GetTypeExpression (lexer.Location), lexer.Location);
}
| USING error {
CheckIdentifierToken (yyToken);
@@ -348,7 +349,8 @@
using_namespace_directive
: USING namespace_name SEMICOLON
{
- current_namespace.Using ((string) $2, lexer.Location);
+ MemberName ns_name = (MemberName) $2;
+ current_namespace.Using (ns_name.GetTypeExpression
(lexer.Location), lexer.Location);
}
;
@@ -401,7 +403,7 @@
if (name.TypeArguments != null)
syntax_error (lexer.Location, "namespace name
expected");
- $$ = name.GetName ();
+ $$ = name;
}
;
Modified: trunk/mcs/gmcs/namespace.cs
===================================================================
--- trunk/mcs/gmcs/namespace.cs 2005-03-21 17:10:19 UTC (rev 42050)
+++ trunk/mcs/gmcs/namespace.cs 2005-03-21 18:11:45 UTC (rev 42051)
@@ -229,37 +229,40 @@
// exist.
//
public class UsingEntry {
- public readonly string Name;
+ public Expression Name;
public readonly NamespaceEntry NamespaceEntry;
public readonly Location Location;
- public UsingEntry (NamespaceEntry entry, string name,
Location loc)
+ public UsingEntry (NamespaceEntry entry, Expression
name, Location loc)
{
Name = name;
NamespaceEntry = entry;
Location = loc;
}
- Namespace resolved_ns;
+ internal FullNamedExpression resolved;
public Namespace Resolve ()
{
- if (resolved_ns != null)
- return resolved_ns;
+ if (resolved != null)
+ return resolved as Namespace;
- FullNamedExpression resolved =
NamespaceEntry.LookupForUsing (Name, Location);
- resolved_ns = resolved as Namespace;
- return resolved_ns;
+ DeclSpace root = RootContext.Tree.Types;
+ root.NamespaceEntry = NamespaceEntry;
+ resolved = Name.ResolveAsTypeStep
(root.EmitContext);
+ root.NamespaceEntry = null;
+
+ return resolved as Namespace;
}
}
public class AliasEntry {
public readonly string Name;
- public readonly MemberName Alias;
+ public readonly Expression Alias;
public readonly NamespaceEntry NamespaceEntry;
public readonly Location Location;
- public AliasEntry (NamespaceEntry entry, string name,
MemberName alias, Location loc)
+ public AliasEntry (NamespaceEntry entry, string name,
Expression alias, Location loc)
{
Name = name;
Alias = alias;
@@ -274,55 +277,62 @@
if (resolved != null)
return resolved;
- //
- // GENERICS: Cope with the expression and not
with the string
- // this will fail with `using A = Stack<int>'
- //
-
- string alias = Alias.GetTypeName ();
+ DeclSpace root = RootContext.Tree.Types;
+ root.NamespaceEntry = NamespaceEntry;
+ resolved = Alias.ResolveAsTypeStep
(root.EmitContext);
+ root.NamespaceEntry = null;
- resolved = NamespaceEntry.LookupForUsing
(alias, Location);
- if (resolved == null)
- return null;
-
- if (Alias.TypeArguments == null)
- return resolved;
-
- EmitContext ec =
RootContext.Tree.Types.EmitContext;
- resolved = new TypeAliasExpression (resolved,
Alias.TypeArguments, Location);
- resolved = resolved.ResolveAsTypeStep (ec);
-
return resolved;
}
}
public NamespaceEntry (NamespaceEntry parent, SourceFile file,
string name, Location loc)
- : this (parent, file, name, false, loc)
- { }
-
- protected NamespaceEntry (NamespaceEntry parent, SourceFile
file, string name, bool is_implicit, Location loc)
{
this.parent = parent;
this.file = file;
- this.IsImplicit = is_implicit;
+ this.IsImplicit = false;
this.ID = ++next_id;
- if (!is_implicit && (parent != null))
+ if (parent != null)
ns = parent.NS.GetNamespace (name, true);
else if (name != null)
ns = Namespace.LookupNamespace (name, true);
else
ns = Namespace.Root;
ns.AddNamespaceEntry (this);
+ this.FullName = ns.Name;
+ }
- if ((parent != null) && (parent.NS != ns.Parent))
- implicit_parent = new NamespaceEntry (parent,
file, ns.Parent.Name, true, loc);
- else
- implicit_parent = parent;
+ private NamespaceEntry (NamespaceEntry parent, SourceFile file,
Namespace ns)
+ {
+ this.parent = parent;
+ this.file = file;
+ this.IsImplicit = true;
+ this.ID = ++next_id;
+ this.ns = ns;
this.FullName = ns.Name;
}
+ //
+ // According to section 16.3.1 (using-alias-directive), the
namespace-or-type-name is
+ // resolved as if the immediately containing namespace body has
no using-directives.
+ //
+ // Section 16.3.2 says that the same rule is applied when
resolving the namespace-name
+ // in the using-namespace-directive.
+ //
+ // To implement these rules, the expressions in the using
directives are resolved using
+ // the "doppelganger" (ghostly bodiless duplicate).
+ //
+ NamespaceEntry doppelganger;
+ NamespaceEntry Doppelganger {
+ get {
+ if (!IsImplicit && doppelganger == null)
+ doppelganger = new NamespaceEntry
(ImplicitParent, file, ns);
+ return doppelganger;
+ }
+ }
+
static int next_id = 0;
public readonly string FullName;
public readonly int ID;
@@ -342,6 +352,13 @@
public NamespaceEntry ImplicitParent {
get {
+ if (parent == null)
+ return null;
+ if (implicit_parent == null) {
+ implicit_parent = (parent.NS ==
ns.Parent)
+ ? parent
+ : new NamespaceEntry (parent,
file, ns.Parent);
+ }
return implicit_parent;
}
}
@@ -354,32 +371,34 @@
/// <summary>
/// Records a new namespace for resolving name references
/// </summary>
- public void Using (string ns, Location loc)
+ public void Using (Expression ns, Location loc)
{
+ string name = ns.ToString ();
if (DeclarationFound){
Report.Error (1529, loc, "A using clause must
precede all other namespace elements");
return;
}
- if (ns == FullName)
+ if (name == FullName)
return;
if (using_clauses == null)
using_clauses = new ArrayList ();
foreach (UsingEntry old_entry in using_clauses) {
- if (old_entry.Name == ns) {
+ if (old_entry.Name.ToString () == name) {
if (RootContext.WarningLevel >= 3)
- Report.Warning (105, loc, "The
using directive for '{0}' appeared previously in this namespace", ns);
+ Report.Warning (105, loc, "The
using directive for '{0}' appeared previously in this namespace", name);
return;
}
}
-
- UsingEntry ue = new UsingEntry (this, ns, loc);
+
+
+ UsingEntry ue = new UsingEntry (Doppelganger, ns, loc);
using_clauses.Add (ue);
}
- public void UsingAlias (string name, MemberName alias, Location
loc)
+ public void UsingAlias (string name, Expression alias, Location
loc)
{
if (DeclarationFound){
Report.Error (1529, loc, "A using clause must
precede all other namespace elements");
@@ -395,7 +414,7 @@
return;
}
- aliases [name] = new AliasEntry (this, name, alias,
loc);
+ aliases [name] = new AliasEntry (Doppelganger, name,
alias, loc);
}
public FullNamedExpression LookupAlias (string alias)
@@ -407,93 +426,51 @@
return entry == null ? null : entry.Resolve ();
}
- //
- // According to section 16.3.1 (using-alias-directive), the
namespace-or-type-name is
- // resolved as if the immediately containing namespace body has
no using-directives.
- //
- // Section 16.3.2 says that the same rule is applied when
resolving the namespace-name
- // in the using-namespace-directive.
- //
- public FullNamedExpression LookupForUsing (string dotted_name,
Location loc)
+ public FullNamedExpression LookupNamespaceOrType (DeclSpace ds,
string name, Location loc)
{
- int pos = dotted_name.IndexOf ('.');
- string simple_name = dotted_name;
+ FullNamedExpression resolved = null;
string rest = null;
+
+ // If name is of the form `N.I', first lookup `N', then
search a member `I' in it.
+ int pos = name.IndexOf ('.');
if (pos >= 0) {
- simple_name = dotted_name.Substring (0, pos);
- rest = dotted_name.Substring (pos + 1);
+ rest = name.Substring (pos + 1);
+ name = name.Substring (0, pos);
}
- FullNamedExpression o = NS.Lookup (null, simple_name,
loc);
- if (o == null && ImplicitParent != null)
- o = ImplicitParent.LookupNamespaceOrType (null,
simple_name, loc);
+ for (NamespaceEntry curr_ns = this; curr_ns != null;
curr_ns = curr_ns.ImplicitParent) {
+ if ((resolved = curr_ns.Lookup (ds, name, loc))
!= null)
+ break;
+ }
- if (o == null || rest == null)
- return o;
+ if (resolved == null || rest == null)
+ return resolved;
- Namespace ns = o as Namespace;
+ Namespace ns = resolved as Namespace;
if (ns != null)
- return ns.Lookup (null, rest, loc);
-
- Type nested = TypeManager.LookupType (o.FullName + "."
+ rest);
- if (nested == null)
+ return ns.Lookup (ds, rest, loc);
+
+ Type nested = TypeManager.LookupType (resolved.FullName
+ "." + rest);
+ if ((nested == null) || ((ds != null) &&
!ds.CheckAccessLevel (nested)))
return null;
return new TypeExpression (nested, Location.Null);
}
- public FullNamedExpression LookupNamespaceOrType (DeclSpace ds,
string name, Location loc)
- {
- FullNamedExpression resolved = null;
- for (NamespaceEntry curr_ns = this; curr_ns != null;
curr_ns = curr_ns.ImplicitParent) {
- if ((resolved = curr_ns.Lookup (ds, name, loc))
!= null)
- break;
- }
- return resolved;
- }
-
private FullNamedExpression Lookup (DeclSpace ds, string name,
Location loc)
{
- FullNamedExpression o;
- Namespace ns;
+ // Precondition: Only simple names (no dots) will be
looked up with this function.
//
- // If name is of the form `N.I', first lookup `N', then
search a member `I' in it.
- //
- // FIXME: Remove this block. Only simple names should
come here.
- // The bug: The loop in LookupNamespaceOrType
continues if
- // the lookup for N succeeds but the nested
lookup for I fails.
- // This is one part of #52697.
- //
- int pos = name.IndexOf ('.');
- if (pos >= 0) {
- string first = name.Substring (0, pos);
- string last = name.Substring (pos + 1);
-
- o = Lookup (ds, first, loc);
- if (o == null)
- return null;
-
- ns = o as Namespace;
- if (ns != null) {
- o = ns.Lookup (ds, last, loc);
- return o;
- }
-
- Type nested = TypeManager.LookupType
(o.FullName + "." + last);
- if ((nested == null) || ((ds != null) &&
!ds.CheckAccessLevel (nested)))
- return null;
-
- return new TypeExpression (nested,
Location.Null);
- }
-
- //
// Check whether it's in the namespace.
//
- o = NS.Lookup (ds, name, loc);
+ FullNamedExpression o = NS.Lookup (ds, name, loc);
if (o != null)
return o;
+ if (IsImplicit)
+ return null;
+
//
// Check aliases.
//
@@ -501,9 +478,6 @@
if (o != null)
return o;
- if (name.IndexOf ('.') > 0)
- return null;
-
//
// Check using entries.
//
@@ -561,7 +535,7 @@
if (using_clauses != null) {
using_list = new string [using_clauses.Count];
for (int i = 0; i < using_clauses.Count; i++)
- using_list [i] = ((UsingEntry)
using_clauses [i]).Name;
+ using_list [i] = ((UsingEntry)
using_clauses [i]).Name.ToString ();
} else {
using_list = new string [0];
}
@@ -629,8 +603,8 @@
if (ue.Resolve () != null)
continue;
- if (LookupForUsing (ue.Name,
ue.Location) == null)
- error246 (ue.Location, ue.Name);
+ if (ue.resolved == null)
+ error246 (ue.Location,
ue.Name.ToString ());
else
Report.Error (138, ue.Location,
"The using keyword only lets you specify a namespace, " +
"`" + ue.Name +
"' is a class not a namespace.");
@@ -645,7 +619,7 @@
if (alias.Resolve () != null)
continue;
- error246 (alias.Location,
alias.Alias.GetTypeName ());
+ error246 (alias.Location,
alias.Alias.ToString ());
}
}
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches