Merge pull request #5010 from Unity-Technologies/boehm-gc-alloc-fixed-sre
[mono.git] / mcs / mcs / namespace.cs
index 0a35cc4c61e7fd8212c58c7a81277026a4193cd2..3314ca2d48c24d8341e6c44faf7523343d0fc182 100644 (file)
@@ -70,6 +70,9 @@ namespace Mono.CSharp {
                        List<string> res = null;
 
                        foreach (var ns in all_namespaces) {
+                               if (ns.Key.Length == 0)
+                                       continue;
+
                                var methods = ns.Value.LookupExtensionMethod (ctx, name, arity);
                                if (methods != null) {
                                        if (res == null)
@@ -249,7 +252,7 @@ namespace Mono.CSharp {
                                return null;
 
                        foreach (var ts in found) {
-                               if (ts.Arity == arity || mode == LookupMode.NameOf) {
+                               if (ts.Arity == arity) {
                                        if (best == null) {
                                                if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility)
                                                        continue;
@@ -276,6 +279,9 @@ namespace Mono.CSharp {
                                                break;
                                        }
 
+                                       if (ts.Kind == MemberKind.MissingType)
+                                               continue;
+
                                        if (best.MemberDefinition.IsImported)
                                                best = ts;
 
@@ -618,8 +624,8 @@ namespace Mono.CSharp {
                        if (include_files == null)
                                include_files = new Dictionary<string, SourceFile> ();
 
-                       if (!include_files.ContainsKey (file.FullPathName))
-                               include_files.Add (file.FullPathName, file);
+                       if (!include_files.ContainsKey (file.OriginalFullPathName))
+                               include_files.Add (file.OriginalFullPathName, file);
                }
 
                public void AddDefine (string value)
@@ -642,7 +648,7 @@ namespace Mono.CSharp {
                {
                        var sw = Module.DeclaringAssembly.SymbolWriter;
                        if (sw != null) {
-                               CreateUnitSymbolInfo (sw);
+                               CreateUnitSymbolInfo (sw, Compiler.Settings.PathMap);
                        }
 
                        base.PrepareEmit ();
@@ -651,14 +657,14 @@ namespace Mono.CSharp {
                //
                // Creates symbol file index in debug symbol file
                //
-               void CreateUnitSymbolInfo (MonoSymbolFile symwriter)
+               void CreateUnitSymbolInfo (MonoSymbolFile symwriter, List<KeyValuePair<string, string>> pathMap)
                {
-                       var si = file.CreateSymbolInfo (symwriter);
+                       var si = file.CreateSymbolInfo (symwriter, pathMap);
                        comp_unit = new CompileUnitEntry (symwriter, si);
 
                        if (include_files != null) {
                                foreach (SourceFile include in include_files.Values) {
-                                       si = include.CreateSymbolInfo (symwriter);
+                                       si = include.CreateSymbolInfo (symwriter, pathMap);
                                        comp_unit.AddFile (si);
                                }
                        }
@@ -697,7 +703,7 @@ namespace Mono.CSharp {
 
                public new readonly NamespaceContainer Parent;
 
-               List<UsingNamespace> clauses;
+               List<UsingClause> clauses;
 
                // Used by parsed to check for parser errors
                public bool DeclarationFound;
@@ -742,7 +748,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               public List<UsingNamespace> Usings {
+               public List<UsingClause> Usings {
                        get {
                                return clauses;
                        }
@@ -756,14 +762,14 @@ namespace Mono.CSharp {
 
                #endregion
 
-               public void AddUsing (UsingNamespace un)
+               public void AddUsing (UsingClause un)
                {
                        if (DeclarationFound){
                                Compiler.Report.Error (1529, un.Location, "A using clause must precede all other namespace elements except extern alias declarations");
                        }
 
                        if (clauses == null)
-                               clauses = new List<UsingNamespace> ();
+                               clauses = new List<UsingClause> ();
 
                        clauses.Add (un);
                }
@@ -780,7 +786,7 @@ namespace Mono.CSharp {
                void AddAlias (UsingAliasNamespace un)
                {
                        if (clauses == null) {
-                               clauses = new List<UsingNamespace> ();
+                               clauses = new List<UsingClause> ();
                        } else {
                                foreach (var entry in clauses) {
                                        var a = entry as UsingAliasNamespace;
@@ -835,7 +841,7 @@ namespace Mono.CSharp {
                                        //
                                        // Same name conflict in different namespace containers
                                        //
-                                       var conflict = ns.GetAllTypes (name);
+                                       var conflict = ns.GetAllTypes (mn.Name);
                                        if (conflict != null) {
                                                foreach (var e in conflict) {
                                                        if (e.Arity == mn.Arity) {
@@ -870,7 +876,7 @@ namespace Mono.CSharp {
                        base.EmitContainer ();
                }
 
-               public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, int position)
+               public ExtensionMethodCandidates LookupExtensionMethod (IMemberContext invocationContext, string name, int arity, int position)
                {
                        //
                        // Here we try to resume the search for extension method at the point
@@ -951,22 +957,18 @@ namespace Mono.CSharp {
                                                candidates.AddRange (a);
                                }
 
-                               if (candidates != null)
-                                       return new ExtensionMethodCandidates (invocationContext, candidates, this, position);
-                       }
-
-                       // LAMESPEC: TODO no spec about priority over normal extension methods yet
-                       if (types_using_table != null) {
-                               foreach (var t in types_using_table) {
+                               if (types_using_table != null) {
+                                       foreach (var t in types_using_table) {
 
-                                       var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
-                                       if (res == null)
-                                               continue;
+                                               var res = t.MemberCache.FindExtensionMethods (invocationContext, name, arity);
+                                               if (res == null)
+                                                       continue;
 
-                                       if (candidates == null)
-                                               candidates = res;
-                                       else
-                                               candidates.AddRange (res);
+                                               if (candidates == null)
+                                                       candidates = res;
+                                               else
+                                                       candidates.AddRange (res);
+                                       }
                                }
 
                                if (candidates != null)
@@ -1062,8 +1064,12 @@ namespace Mono.CSharp {
                                        continue;
 
                                UsingAliasNamespace uan;
-                               if (n.aliases.TryGetValue (name, out uan))
+                               if (n.aliases.TryGetValue (name, out uan)) {
+                                       if (uan.ResolvedExpression == null)
+                                               uan.Define (n);
+
                                        return uan.ResolvedExpression;
+                               }
                        }
 
                        return null;
@@ -1091,6 +1097,9 @@ namespace Mono.CSharp {
                                                        GetSignatureForError (), name);
                                        }
 
+                                       if (uan.ResolvedExpression == null)
+                                               uan.Define (this);
+
                                        return uan.ResolvedExpression;
                                }
                        }
@@ -1138,10 +1147,7 @@ namespace Mono.CSharp {
                                var better = Namespace.IsImportedTypeOverride (Module, texpr_match.Type, texpr_fne.Type);
                                if (better == null) {
                                        if (mode == LookupMode.Normal) {
-                                               Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type);
-                                               Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type);
-                                               Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
-                                                       name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ());
+                                               Error_AmbiguousReference (name, texpr_match, texpr_fne, loc);
                                        }
 
                                        return match;
@@ -1151,10 +1157,37 @@ namespace Mono.CSharp {
                                        match = texpr_fne;
                        }
 
+                       if (types_using_table != null && (mode & LookupMode.IgnoreStaticUsing) == 0) {
+                               foreach (var using_type in types_using_table) {
+                                       var type = MemberCache.FindNestedType (using_type, name, arity, true);
+                                       if (type == null)
+                                               continue;
+                                       
+                                       fne = new TypeExpression (type, loc);
+                                       if (match == null) {
+                                               match = fne;
+                                               continue;
+                                       }
+
+                                       if (mode == LookupMode.Normal) {
+                                               Error_AmbiguousReference (name, match, fne, loc);
+                                       }
+                               }
+                       }
+
                        return match;
                }
 
-               public static MethodGroupExpr LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc)
+               void Error_AmbiguousReference (string name, FullNamedExpression a, FullNamedExpression b, Location loc)
+               {
+                       var report = Compiler.Report;
+                       report.SymbolRelatedToPreviousError (a.Type);
+                       report.SymbolRelatedToPreviousError (b.Type);
+                       report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'",
+                               name, a.GetSignatureForError (), b.GetSignatureForError ());
+               }
+
+               public static Expression LookupStaticUsings (IMemberContext mc, string name, int arity, Location loc)
                {
                        for (var m = mc.CurrentMemberDefinition; m != null; m = m.Parent) {
 
@@ -1166,25 +1199,36 @@ namespace Mono.CSharp {
                                if (nc.types_using_table != null) {
                                        foreach (var using_type in nc.types_using_table) {
                                                var members = MemberCache.FindMembers (using_type, name, true);
-                                               if (members != null) {
-                                                       foreach (var member in members) {
-                                                               if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0)
+                                               if (members == null)
+                                                       continue;
+                                               
+                                               foreach (var member in members) {
+                                                       if ((member.Kind & MemberKind.NestedMask) != 0) {
+                                                               // non-static nested type is included with using static
+                                                       } else {
+                                                               if ((member.Modifiers & Modifiers.STATIC) == 0)
                                                                        continue;
 
-                                                               if (arity > 0 && member.Arity != arity)
+                                                               if ((member.Modifiers & Modifiers.METHOD_EXTENSION) != 0)
                                                                        continue;
+                                                       }
 
-                                                               if (candidates == null)
-                                                                       candidates = new List<MemberSpec> ();
+                                                       if (arity > 0 && member.Arity != arity)
+                                                               continue;
 
-                                                               candidates.Add (member);
-                                                       }
+                                                       if (candidates == null)
+                                                               candidates = new List<MemberSpec> ();
+
+                                                       candidates.Add (member);
                                                }
                                        }
                                }
 
-                               if (candidates != null)
-                                       return new MethodGroupExpr (candidates, null, loc);
+                               if (candidates != null) {
+                                       var expr = Expression.MemberLookupToExpression (mc, candidates, false, null, name, arity, Expression.MemberLookupRestrictions.None, loc);
+                                       if (expr != null)
+                                               return expr;
+                               }
                        }
 
                        return null;
@@ -1232,21 +1276,25 @@ namespace Mono.CSharp {
                                                continue;
                                        }
 
-                                       entry.Define (this);
+                                       try {
+                                               entry.Define (this);
+                                       } finally {
+                                               //
+                                               // It's needed for repl only, when using clause cannot be resolved don't hold it in
+                                               // global list which is resolved for every evaluation
+                                               //
+                                               if (entry.ResolvedExpression == null) {
+                                                       clauses.RemoveAt (i--);
+                                               }
+                                       }
 
-                                       //
-                                       // It's needed for repl only, when using clause cannot be resolved don't hold it in
-                                       // global list which is resolved for each evaluation
-                                       //
-                                       if (entry.ResolvedExpression == null) {
-                                               clauses.RemoveAt (i--);
+                                       if (entry.ResolvedExpression == null)
                                                continue;
-                                       }
 
                                        var using_ns = entry.ResolvedExpression as NamespaceExpression;
                                        if (using_ns == null) {
 
-                                               var type = ((TypeExpr)entry.ResolvedExpression).Type;
+                                               var type = entry.ResolvedExpression.Type;
 
                                                if (types == null)
                                                        types = new List<TypeSpec> ();
@@ -1279,18 +1327,32 @@ namespace Mono.CSharp {
                                        for (int i = 0; i < clauses.Count; ++i) {
                                                var entry = clauses[i];
                                                if (entry.Alias != null) {
-                                                       entry.Define (this);
-                                                       if (entry.ResolvedExpression != null) {
-                                                               aliases.Add (entry.Alias.Value, (UsingAliasNamespace) entry);
-                                                       }
-
-                                                       clauses.RemoveAt (i--);
+                                                       aliases[entry.Alias.Value] = (UsingAliasNamespace) entry;
                                                }
                                        }
                                }
                        }
                }
 
+               protected override void DoDefineContainer ()
+               {
+                       base.DoDefineContainer ();
+
+                       if (clauses != null) {
+                               for (int i = 0; i < clauses.Count; ++i) {
+                                       var entry = clauses[i];
+
+                                       //
+                                       // Finish definition of using aliases not visited during container
+                                       // definition
+                                       //
+                                       if (entry.Alias != null && entry.ResolvedExpression == null) {
+                                               entry.Define (this);
+                                       }
+                               }
+                       }
+               }
+
                public void EnableRedefinition ()
                {
                        is_defined = false;
@@ -1330,7 +1392,7 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               void Warning_DuplicateEntry (UsingNamespace entry)
+               void Warning_DuplicateEntry (UsingClause entry)
                {
                        Compiler.Report.Warning (105, 3, entry.Location,
                                "The using directive for `{0}' appeared previously in this namespace",
@@ -1343,13 +1405,72 @@ namespace Mono.CSharp {
                }
        }
 
-       public class UsingNamespace
+       public class UsingNamespace : UsingClause
+       {
+               public UsingNamespace (ATypeNameExpression expr, Location loc)
+                       : base (expr, loc)
+               {
+               }
+
+               public override void Define (NamespaceContainer ctx)
+               {
+                       base.Define (ctx);
+
+                       var ns = resolved as NamespaceExpression;
+                       if (ns != null)
+                               return;
+
+                       if (resolved != null) {
+                               var compiler = ctx.Module.Compiler;
+                               var type = resolved.Type;
+                               resolved = null;
+
+                               compiler.Report.SymbolRelatedToPreviousError (type);
+                               compiler.Report.Error (138, Location,
+                                       "A `using' directive can only be applied to namespaces but `{0}' denotes a type. Consider using a `using static' instead",
+                                       type.GetSignatureForError ());
+                       }
+               }
+       }
+
+       public class UsingType : UsingClause
+       {
+               public UsingType (ATypeNameExpression expr, Location loc)
+                       : base (expr, loc)
+               {
+               }
+
+               public override void Define (NamespaceContainer ctx)
+               {
+                       base.Define (ctx);
+
+                       if (resolved == null)
+                               return;
+
+                       var ns = resolved as NamespaceExpression;
+                       if (ns != null) {
+                               var compiler = ctx.Module.Compiler;
+                               compiler.Report.Error (7007, Location,
+                                       "A 'using static' directive can only be applied to types but `{0}' denotes a namespace. Consider using a `using' directive instead",
+                                       ns.GetSignatureForError ());
+                               return;
+                       }
+
+                       // TODO: Need to move it to post_process_using_aliases
+                       //ObsoleteAttribute obsolete_attr = resolved.Type.GetAttributeObsolete ();
+                       //if (obsolete_attr != null) {
+                       //      AttributeTester.Report_ObsoleteMessage (obsolete_attr, resolved.GetSignatureForError (), Location, ctx.Compiler.Report);
+                       //}
+               }
+       }
+
+       public class UsingClause
        {
                readonly ATypeNameExpression expr;
                readonly Location loc;
                protected FullNamedExpression resolved;
 
-               public UsingNamespace (ATypeNameExpression expr, Location loc)
+               public UsingClause (ATypeNameExpression expr, Location loc)
                {
                        this.expr = expr;
                        this.loc = loc;
@@ -1391,29 +1512,6 @@ namespace Mono.CSharp {
                public virtual void Define (NamespaceContainer ctx)
                {
                        resolved = expr.ResolveAsTypeOrNamespace (ctx, false);
-                       var ns = resolved as NamespaceExpression;
-                       if (ns != null)
-                               return;
-
-                       if (resolved != null) {
-                               var compiler = ctx.Module.Compiler;
-                               var type = resolved.Type;
-                               if (compiler.Settings.Version >= LanguageVersion.V_6) {
-                                       if (!type.IsClass || !type.IsStatic) {
-                                               compiler.Report.SymbolRelatedToPreviousError (type);
-                                               compiler.Report.Error (7007, Location,
-                                                       "`{0}' is not a static class. A using namespace directive can only be applied to static classes or namespace",
-                                                       GetSignatureForError ());
-                                       }
-
-                                       return;
-                               }
-
-                               compiler.Report.SymbolRelatedToPreviousError (type);
-                               compiler.Report.Error (138, Location,
-                                       "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces",
-                                       GetSignatureForError ());
-                       }
                }
 
                public override string ToString()
@@ -1503,7 +1601,7 @@ namespace Mono.CSharp {
                                throw new NotImplementedException ();
                        }
 
-                       public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
+                       public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
                        {
                                return null;
                        }
@@ -1568,7 +1666,8 @@ namespace Mono.CSharp {
                        // We achieve that by introducing alias-context which redirect any local
                        // namespace or type resolve calls to parent namespace
                        //
-                       resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false);
+                       resolved = NamespaceExpression.ResolveAsTypeOrNamespace (new AliasContext (ctx), false) ??
+                               new TypeExpression (InternalType.ErrorType, NamespaceExpression.Location);
                }
        }
 }