changeset 2857:54a0b6cae9c5

Merge
author mfang
date Thu, 11 Jun 2015 10:11:18 -0700
parents d4051d4f5daf 380f6c17ea01
children 976523f1d562
files
diffstat 15 files changed, 604 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Scope.java	Wed Jun 10 14:22:04 2015 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Scope.java	Thu Jun 11 10:11:18 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -241,12 +241,16 @@
         listeners = listeners.prepend(sl);
     }
 
-    /** Remove symbol from this scope.  Used when an inner class
-     *  attribute tells us that the class isn't a package member.
+    /** Remove symbol from this scope.
      */
-    public void remove(Symbol sym) {
+    public void remove(final Symbol sym) {
         Assert.check(shared == 0);
-        Entry e = lookup(sym.name);
+        Entry e = lookup(sym.name, new Filter<Symbol>() {
+            @Override
+            public boolean accepts(Symbol candidate) {
+                return candidate == sym;
+            }
+        });
         if (e.scope == null) return;
 
         // remove e from table and shadowed list;
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Jun 10 14:22:04 2015 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Jun 11 10:11:18 2015 -0700
@@ -2694,74 +2694,98 @@
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="compute transitive closure of all members in given site">
-    class MembersClosureCache extends SimpleVisitor<CompoundScope, Boolean> {
-
-        private WeakHashMap<TypeSymbol, Entry> _map =
-                new WeakHashMap<TypeSymbol, Entry>();
-
-        class Entry {
-            final boolean skipInterfaces;
-            final CompoundScope compoundScope;
-
-            public Entry(boolean skipInterfaces, CompoundScope compoundScope) {
-                this.skipInterfaces = skipInterfaces;
-                this.compoundScope = compoundScope;
+    class MembersClosureCache extends SimpleVisitor<Scope.CompoundScope, Void> {
+
+        private Map<TypeSymbol, CompoundScope> _map = new HashMap<>();
+
+        Set<TypeSymbol> seenTypes = new HashSet<>();
+
+        class MembersScope extends CompoundScope {
+
+            CompoundScope scope;
+
+            public MembersScope(CompoundScope scope) {
+                super(scope.owner);
+                this.scope = scope;
             }
 
-            boolean matches(boolean skipInterfaces) {
-                return this.skipInterfaces == skipInterfaces;
+            Filter<Symbol> combine(final Filter<Symbol> sf) {
+                return new Filter<Symbol>() {
+                    @Override
+                    public boolean accepts(Symbol s) {
+                        return !s.owner.isInterface() && (sf == null || sf.accepts(s));
+                    }
+                };
+            }
+
+            @Override
+            public Iterable<Symbol> getElements(Filter<Symbol> sf) {
+                return scope.getElements(combine(sf));
+            }
+
+            @Override
+            public Iterable<Symbol> getElementsByName(Name name, Filter<Symbol> sf) {
+                return scope.getElementsByName(name, combine(sf));
+            }
+
+            @Override
+            public int getMark() {
+                return scope.getMark();
             }
         }
 
-        List<TypeSymbol> seenTypes = List.nil();
+        CompoundScope nilScope;
 
         /** members closure visitor methods **/
 
-        public CompoundScope visitType(Type t, Boolean skipInterface) {
-            return null;
+        public CompoundScope visitType(Type t, Void _unused) {
+            if (nilScope == null) {
+                nilScope = new CompoundScope(syms.noSymbol);
+            }
+            return nilScope;
         }
 
         @Override
-        public CompoundScope visitClassType(ClassType t, Boolean skipInterface) {
-            if (seenTypes.contains(t.tsym)) {
+        public CompoundScope visitClassType(ClassType t, Void _unused) {
+            if (!seenTypes.add(t.tsym)) {
                 //this is possible when an interface is implemented in multiple
-                //superclasses, or when a classs hierarchy is circular - in such
+                //superclasses, or when a class hierarchy is circular - in such
                 //cases we don't need to recurse (empty scope is returned)
                 return new CompoundScope(t.tsym);
             }
             try {
-                seenTypes = seenTypes.prepend(t.tsym);
+                seenTypes.add(t.tsym);
                 ClassSymbol csym = (ClassSymbol)t.tsym;
-                Entry e = _map.get(csym);
-                if (e == null || !e.matches(skipInterface)) {
-                    CompoundScope membersClosure = new CompoundScope(csym);
-                    if (!skipInterface) {
-                        for (Type i : interfaces(t)) {
-                            membersClosure.addSubScope(visit(i, skipInterface));
-                        }
+                CompoundScope membersClosure = _map.get(csym);
+                if (membersClosure == null) {
+                    membersClosure = new CompoundScope(csym);
+                    for (Type i : interfaces(t)) {
+                        membersClosure.addSubScope(visit(i, null));
                     }
-                    membersClosure.addSubScope(visit(supertype(t), skipInterface));
+                    membersClosure.addSubScope(visit(supertype(t), null));
                     membersClosure.addSubScope(csym.members());
-                    e = new Entry(skipInterface, membersClosure);
-                    _map.put(csym, e);
+                    _map.put(csym, membersClosure);
                 }
-                return e.compoundScope;
+                return membersClosure;
             }
             finally {
-                seenTypes = seenTypes.tail;
+                seenTypes.remove(t.tsym);
             }
         }
 
         @Override
-        public CompoundScope visitTypeVar(TypeVar t, Boolean skipInterface) {
-            return visit(t.getUpperBound(), skipInterface);
+        public CompoundScope visitTypeVar(TypeVar t, Void _unused) {
+            return visit(t.getUpperBound(), null);
         }
     }
 
     private MembersClosureCache membersCache = new MembersClosureCache();
 
     public CompoundScope membersClosure(Type site, boolean skipInterface) {
-        return membersCache.visit(site, skipInterface);
+        CompoundScope cs = membersCache.visit(site, null);
+        if (cs == null)
+            Assert.error("type " + site);
+        return skipInterface ? membersCache.new MembersScope(cs) : cs;
     }
     // </editor-fold>
 
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jun 10 14:22:04 2015 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jun 11 10:11:18 2015 -0700
@@ -825,9 +825,18 @@
     }
 
     public void visitClassDef(JCClassDecl tree) {
-        // Local classes have not been entered yet, so we need to do it now:
-        if ((env.info.scope.owner.kind & (VAR | MTH)) != 0)
+        // Local and anonymous classes have not been entered yet, so we need to
+        // do it now.
+        if ((env.info.scope.owner.kind & (VAR | MTH)) != 0) {
             enter.classEnter(tree, env);
+        } else {
+            // If this class declaration is part of a class level annotation,
+            // as in @MyAnno(new Object() {}) class MyClass {}, enter it in
+            // order to simplify later steps and allow for sensible error
+            // messages.
+            if (env.tree.hasTag(NEWCLASS) && TreeInfo.isInAnnotation(env, tree))
+                enter.classEnter(tree, env);
+        }
 
         ClassSymbol c = tree.sym;
         if (c == null) {
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jun 10 14:22:04 2015 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Thu Jun 11 10:11:18 2015 -0700
@@ -1256,6 +1256,9 @@
                         return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType);
                     case APPLY:
                         return true;
+                    case NEWCLASS:
+                        JCNewClass nc = (JCNewClass) rec;
+                        return nc.encl == null && nc.def == null && !TreeInfo.isDiamond(nc);
                     default:
                         return false;
                 }
@@ -1310,17 +1313,24 @@
             Type site;
 
             if (rec != null) {
-                if (rec.hasTag(APPLY)) {
-                    Symbol recSym = quicklyResolveMethod(env, (JCMethodInvocation) rec);
-                    if (recSym == null)
-                        return null;
-                    Symbol resolvedReturnType =
-                            analyzeCandidateMethods(recSym, syms.errSymbol, returnSymbolAnalyzer);
-                    if (resolvedReturnType == null)
-                        return null;
-                    site = resolvedReturnType.type;
-                } else {
-                    site = attribSpeculative(rec, env, attr.unknownTypeExprInfo).type;
+                switch (rec.getTag()) {
+                    case APPLY:
+                        Symbol recSym = quicklyResolveMethod(env, (JCMethodInvocation) rec);
+                        if (recSym == null)
+                            return null;
+                        Symbol resolvedReturnType =
+                                analyzeCandidateMethods(recSym, syms.errSymbol, returnSymbolAnalyzer);
+                        if (resolvedReturnType == null)
+                            return null;
+                        site = resolvedReturnType.type;
+                        break;
+                    case NEWCLASS:
+                        JCNewClass nc = (JCNewClass) rec;
+                        site = attribSpeculative(nc.clazz, env, attr.unknownTypeExprInfo).type;
+                        break;
+                    default:
+                        site = attribSpeculative(rec, env, attr.unknownTypeExprInfo).type;
+                        break;
                 }
             } else {
                 site = env.enclClass.sym.type;
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jun 10 14:22:04 2015 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jun 11 10:11:18 2015 -0700
@@ -271,7 +271,7 @@
      *  the one of its outer environment
      */
     protected static boolean isStatic(Env<AttrContext> env) {
-        return env.info.staticLevel > env.outer.info.staticLevel;
+        return env.outer != null && env.info.staticLevel > env.outer.info.staticLevel;
     }
 
     /** An environment is an "initializer" if it is a constructor or
--- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Wed Jun 10 14:22:04 2015 -0700
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java	Thu Jun 11 10:11:18 2015 -0700
@@ -28,6 +28,7 @@
 
 
 import com.sun.source.tree.Tree;
+import com.sun.source.util.TreePath;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.comp.AttrContext;
 import com.sun.tools.javac.comp.Env;
@@ -351,6 +352,18 @@
         return (lit.typetag == BOT);
     }
 
+    /** Return true iff this tree is a child of some annotation. */
+    public static boolean isInAnnotation(Env<?> env, JCTree tree) {
+        TreePath tp = TreePath.getPath(env.toplevel, tree);
+        if (tp != null) {
+            for (Tree t : tp) {
+                if (t.getKind() == Tree.Kind.ANNOTATION)
+                    return true;
+            }
+        }
+        return false;
+    }
+
     public static String getCommentText(Env<?> env, JCTree tree) {
         DocCommentTable docComments = (tree.hasTag(JCTree.Tag.TOPLEVEL))
                 ? ((JCCompilationUnit) tree).docComments
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/neg/AnonSubclass.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8028389
+ * @summary javac should output a proper error message when given something
+ * like new Object(){} as annotation argument.
+ *
+ * @compile/fail/ref=AnonSubclass.out -XDrawDiagnostics AnonSubclass.java
+ */
+
+@AnonSubclass(new Object(){})
+@interface AnonSubclass {
+    String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/neg/AnonSubclass.out	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,2 @@
+AnonSubclass.java:10:15: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, java.lang.String)
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/neg/pkg/AnonSubclassOnPkg.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+@interface AnonSubclassOnPkg {
+    String value();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/neg/pkg/package-info.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8028389
+ * @summary javac should output a proper error message when given something
+ * like new Object(){} as annotation argument.
+ *
+ * @compile AnonSubclassOnPkg.java
+ * @compile/fail/ref=package-info.out -XDrawDiagnostics package-info.java
+ */
+
+@AnonSubclassOnPkg(new Object(){})
+package pkg;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/annotations/neg/pkg/package-info.out	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,2 @@
+package-info.java:11:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, java.lang.String)
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/expression/DeeplyChainedNonPolyExpressionTest.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8079613
+ * @summary Ensure that compiler ascertains a class of patently non-poly expressions as such
+ * @run main/timeout=10 DeeplyChainedNonPolyExpressionTest
+ */
+
+public class DeeplyChainedNonPolyExpressionTest {
+    static class JSO {
+
+        JSO put(String s, Object y) {
+            return null;
+        }
+
+        JSO put(java.lang.String x, java.util.Collection<String> y) {
+            return null;
+        }
+
+        JSO put(java.lang.String x, int y) {
+            return null;
+        }
+
+        JSO put(java.lang.String x, long y) {
+            return null;
+        }
+
+        JSO put(java.lang.String x, double y) {
+            return null;
+        }
+
+        JSO put(java.lang.String x, java.util.Map<String, String> y) {
+            return null;
+        }
+
+        JSO put(java.lang.String x, boolean y) {
+            return null;
+        }
+    }
+
+    static class JSA {
+
+        JSA put(Object o) {
+            return null;
+        }
+
+        JSA put(int i, Object x) {
+            return null;
+        }
+
+        JSA put(boolean x) {
+            return null;
+        }
+
+        JSA put(int x) {
+            return null;
+        }
+
+        JSA put(int i, int x) {
+            return null;
+        }
+
+        JSA put(int x, boolean y) {
+            return null;
+        }
+
+        JSA put(int i, long x) {
+            return null;
+        }
+
+        JSA put(long x) {
+            return null;
+        }
+
+        JSA put(java.util.Collection<String> x) {
+            return null;
+        }
+
+        JSA put(int i, java.util.Collection<String> x) {
+            return null;
+        }
+
+        JSA put(int i, java.util.Map<String, String> x) {
+            return null;
+        }
+
+        JSA put(java.util.Map<String, String> x) {
+            return null;
+        }
+
+        JSA put(int i, double x) {
+            return null;
+        }
+
+        JSA put(double x) {
+            return null;
+        }
+    }
+
+    public static void main(String [] args) {
+    }
+    public static void foo() {
+         new JSO()
+          .put("s", new JSA())
+          .put("s", new JSA())
+          .put("s", new JSO()
+            .put("s", new JSO()
+              .put("s", new JSA().put("s"))
+              .put("s", new JSA())
+              .put("s", new JSO()
+                .put("s", new JSO()
+                  .put("s", new JSA().put("s").put("s"))
+                  .put("s", new JSA())
+                  .put("s", new JSO()
+                    .put("s", new JSO()
+                      .put("s", new JSA().put("s").put("s").put("s")
+                            .put("s").put("s").put("s")
+                            .put("s").put("s"))
+                      .put("s", new JSA())
+                      .put("s", new JSO()
+                        .put("s", new JSO()
+                          .put("s", new JSA().put("s"))
+                          .put("s", new JSA())
+                        )
+                      )
+                    )
+                  )
+                )
+                .put("s", new JSO()
+                  .put("s", new JSA().put("s"))
+                  .put("s", new JSA())
+                  .put("s", new JSO()
+                  .put("s", new JSO()
+                    .put("s", new JSA().put("s").put("s"))
+                    .put("s", new JSA())
+                    .put("s", new JSO()
+                      .put("s", new JSO()
+                        .put("s", new JSA().put("s").put("s").put("s")
+                                .put("s").put("s").put("s")
+                                .put("s").put("s"))
+                        .put("s", new JSA())
+                        .put("s", new JSO()
+                          .put("s", new JSO()
+                            .put("s", new JSA().put("s"))
+                            .put("s", new JSA()))
+                          )
+                        )
+                      )
+                    )
+                  )
+                )
+              )
+            )
+          );
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/scope/RemoveSymbolTest.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080842
+ * @summary Ensure Scope impl can cope with remove() when a field and method share the name.
+ * @run main RemoveSymbolTest
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+public class RemoveSymbolTest<W> implements Iterable<W> {
+    static class Widget {
+        private String name;
+        Widget(String s) { name = s; }
+        @Override public String toString() { return name; }
+    }
+
+    private LinkedList<W> data;
+    // Instantiate an Iterable instance using a Lambda expression.
+    // Causes ClassFormatError if a local variable of type Widget is named after one of the methods.
+    private final Iterable<W> myIterator1 = () -> new Iterator<W>() {
+        private W hasNext = null;
+        private int index = 0;
+        @Override public boolean hasNext() { return index < data.size(); }
+        @Override public W next() { return data.get(index++); }
+    };
+
+    // Instantiate an Iterable instance using an anonymous class.
+    // Always works fine regardless of the name of the local variable.
+    private final Iterable<W> myIterator2 =
+        new Iterable<W>() {
+        @Override
+        public Iterator<W> iterator() {
+            return new Iterator<W>() {
+                private W hasNext = null;
+                private int index = 0;
+                @Override public boolean hasNext() { return index < data.size(); }
+                @Override public W next() { return data.get(index++); }
+            };
+        }
+    };
+    public RemoveSymbolTest() { data = new LinkedList<>(); }
+    public void add(W e) { data.add(e); }
+    @Override public String toString() { return data.toString(); }
+    @Override public Iterator<W> iterator() { return myIterator1.iterator(); }
+    public static void main(String[] args) {
+        RemoveSymbolTest<Widget> widgets = new RemoveSymbolTest<>();
+        widgets.add(new Widget("W1"));
+        widgets.add(new Widget("W2"));
+        widgets.add(new Widget("W3"));
+        System.out.println(".foreach() call: ");
+        widgets.forEach(w -> System.out.println(w + " "));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/scope/RemoveSymbolUnitTest.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8080842
+ * @summary Ensure Scope impl can cope with remove() when a field and method share the name.
+ */
+
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Scope.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.file.JavacFileManager;
+
+public class RemoveSymbolUnitTest {
+
+    Context context;
+    Names names;
+    Symtab symtab;
+
+    public static void main(String... args) throws Exception {
+        new RemoveSymbolUnitTest().run();
+    }
+
+    public void run() {
+        context = new Context();
+        JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
+        names = Names.instance(context);
+        symtab = Symtab.instance(context);
+
+        Name hasNext =  names.fromString("hasNext");
+        ClassSymbol clazz = new ClassSymbol(0,
+                                            names.fromString("X"),
+                                            Type.noType,
+                                            symtab.unnamedPackage);
+
+        VarSymbol v = new VarSymbol(0, hasNext, Type.noType, clazz);
+        MethodSymbol m = new MethodSymbol(0, hasNext, Type.noType, clazz);
+
+        // Try enter and remove in different shuffled combinations.
+        // working with fresh scope each time.
+        Scope cs = new Scope(clazz);
+        cs.enter(v);
+        cs.enter(m);
+        cs.remove(v);
+        Symbol s = cs.lookup(hasNext).sym;
+        if (s != m)
+            throw new AssertionError("Wrong symbol");
+
+        cs = new Scope(clazz);
+        cs.enter(m);
+        cs.enter(v);
+        cs.remove(v);
+        s = cs.lookup(hasNext).sym;
+        if (s != m)
+            throw new AssertionError("Wrong symbol");
+
+        cs = new Scope(clazz);
+        cs.enter(v);
+        cs.enter(m);
+        cs.remove(m);
+        s = cs.lookup(hasNext).sym;
+        if (s != v)
+            throw new AssertionError("Wrong symbol");
+
+        cs = new Scope(clazz);
+        cs.enter(m);
+        cs.enter(v);
+        cs.remove(m);
+        s = cs.lookup(hasNext).sym;
+        if (s != v)
+            throw new AssertionError("Wrong symbol");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/types/ScopeListenerTest.java	Thu Jun 11 10:11:18 2015 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8039262
+ * @summary Ensure that using Types.membersClosure does not increase the number of listeners on the
+ *          class's members Scope.
+ */
+
+import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Names;
+import java.lang.reflect.Field;
+import java.util.Collection;
+
+public class ScopeListenerTest {
+
+    public static void main(String[] args) throws Exception {
+        new ScopeListenerTest().run();
+    }
+
+    void run() throws Exception {
+        Context context = new Context();
+        JavacFileManager.preRegister(context);
+        Types types = Types.instance(context);
+        Symtab syms = Symtab.instance(context);
+        Names names = Names.instance(context);
+        types.membersClosure(syms.stringType, true);
+        types.membersClosure(syms.stringType, false);
+
+        Field listenersField = Scope.class.getDeclaredField("listeners");
+
+        listenersField.setAccessible(true);
+
+        int listenerCount =
+                ((Collection) listenersField.get(syms.stringType.tsym.members())).size();
+
+        for (int i = 0; i < 100; i++) {
+            types.membersClosure(syms.stringType, true);
+            types.membersClosure(syms.stringType, false);
+        }
+
+        int newListenerCount
+                = ((Collection) listenersField.get(syms.stringType.tsym.members())).size();
+
+        if (listenerCount != newListenerCount) {
+            throw new AssertionError("Orig listener count: " + listenerCount +
+                                     "; new listener count: " + newListenerCount);
+        }
+
+        for (Symbol s : types.membersClosure(syms.stringType, true).getElements())
+            ;
+        for (Symbol s : types.membersClosure(syms.stringType, false).getElementsByName(names.fromString("substring")))
+            ;
+    }
+
+}