### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java,v retrieving revision 1.181 diff -u -r1.181 ClassScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 20 Oct 2010 05:46:47 -0000 1.181 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java 23 Oct 2010 15:35:41 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -146,6 +147,8 @@ void buildFieldsAndMethods() { buildFields(); buildMethods(); + if ((this.referenceContext.binding.tagBits & TagBits.IsAccessibleViaNonPrivateSub) != 0) + this.referenceContext.binding.tagIndirectlyAccessibleFields(); SourceTypeBinding sourceType = this.referenceContext.binding; if (sourceType.isMemberType() && !sourceType.isLocalType()) @@ -903,6 +906,8 @@ } else { // only want to reach here when no errors are reported sourceType.superclass = superclass; + if (superclass.isPrivate() && !sourceType.isPrivate()) + superclass.tagBits |= TagBits.IsAccessibleViaNonPrivateSub; return true; } } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java,v retrieving revision 1.60 diff -u -r1.60 FieldBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java 22 Oct 2010 22:42:56 -0000 1.60 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java 23 Oct 2010 15:35:42 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 185682 - Increment/decrement operators mark local variables as read + * Stephan Herrmann - Contributions for + * bug 185682 - Increment/decrement operators mark local variables as read + * bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -299,6 +301,8 @@ public final boolean isOrEnclosedByPrivateType() { if ((this.modifiers & ClassFileConstants.AccPrivate) != 0) return true; + if ((this.tagBits & TagBits.IsAccessibleViaNonPrivateSub) != 0) + return false; // visibility leak through non-private subclass return this.declaringClass != null && this.declaringClass.isOrEnclosedByPrivateType(); } /* Answer true if the receiver has private visibility and is used locally Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java,v retrieving revision 1.127 diff -u -r1.127 MethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 7 Sep 2010 13:39:18 -0000 1.127 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 23 Oct 2010 15:35:44 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -705,6 +706,8 @@ public final boolean isOrEnclosedByPrivateType() { if ((this.modifiers & ClassFileConstants.AccPrivate) != 0) return true; + if ((this.tagBits & TagBits.IsAccessibleViaNonPrivateSub) != 0) + return false; // visibility leak through non-private subclass return this.declaringClass != null && this.declaringClass.isOrEnclosedByPrivateType(); } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java,v retrieving revision 1.113 diff -u -r1.113 MethodVerifier.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 17 Aug 2010 14:50:42 -0000 1.113 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java 23 Oct 2010 15:35:47 -0000 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Benjamin Muskalla - Contribution for bug 239066 + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -456,7 +457,7 @@ if (current == null && !isOrEnclosedByPrivateType) { int length = inherited.length; for (int i = 0; i < length; i++){ - inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; + inherited[i].original().tagBits |= TagBits.IsAccessibleViaNonPrivateSub; } } @@ -496,7 +497,7 @@ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed, // inherited methods of super classes are too. current == null case handled already. if (!isOrEnclosedByPrivateType && current != null) { - inheritedMethod.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; + inheritedMethod.original().tagBits |= TagBits.IsAccessibleViaNonPrivateSub; } matchingInherited[++index] = inheritedMethod; for (int j = i + 1; j < length; j++) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java,v retrieving revision 1.117 diff -u -r1.117 MethodVerifier15.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java 22 Oct 2010 04:26:50 -0000 1.117 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java 23 Oct 2010 15:35:48 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -396,7 +397,7 @@ if (current == null && !isOrEnclosedByPrivateType) { int length = inherited.length; for (int i = 0; i < length; i++){ - inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; + inherited[i].original().tagBits |= TagBits.IsAccessibleViaNonPrivateSub; } } if (current == null && this.type.isPublic()) { @@ -466,7 +467,7 @@ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660, if current type is exposed, // inherited methods of super classes are too. current == null case handled already. if (!isOrEnclosedByPrivateType && matchMethod == null && current != null) { - inherited[i].original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; + inherited[i].original().tagBits |= TagBits.IsAccessibleViaNonPrivateSub; } if (skip[i]) continue; MethodBinding inheritedMethod = inherited[i]; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java,v retrieving revision 1.181 diff -u -r1.181 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 15 Sep 2010 15:17:25 -0000 1.181 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 23 Oct 2010 15:35:52 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -1627,4 +1628,13 @@ public FieldBinding[] unResolvedFields() { return this.fields; } + +public void tagIndirectlyAccessibleFields() { + for (int i = 0; i < this.fields.length; i++) { + if (!this.fields[i].isPrivate()) + this.fields[i].tagBits |= TagBits.IsAccessibleViaNonPrivateSub; + } + if (this.superclass.isPrivate()) + ((SourceTypeBinding)this.superclass).tagIndirectlyAccessibleFields(); +} } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java,v retrieving revision 1.44 diff -u -r1.44 TagBits.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java 21 Sep 2010 14:02:58 -0000 1.44 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java 23 Oct 2010 15:35:52 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -122,4 +123,8 @@ // set when type contains non-private constructor(s) long HasNonPrivateConstructor = ASTNode.Bit53L; + + // set on a private class if it has a non-private subclass + // set on a field/method of a private class if it is accessible via a non-private subclass + long IsAccessibleViaNonPrivateSub = ASTNode.Bit54L; } #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java,v retrieving revision 1.36 diff -u -r1.36 ProblemTypeAndMethodTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java 20 Oct 2010 05:47:03 -0000 1.36 +++ src/org/eclipse/jdt/core/tests/compiler/regression/ProblemTypeAndMethodTest.java 23 Oct 2010 15:36:12 -0000 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -5154,6 +5155,152 @@ "----------\n"); } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660 +// check independence of textual order +public void test099a() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " public class C extends B {\n" + + " public void foo(int a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(double a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(boolean a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(byte a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " }\n" + + " private class B extends A {\n" + + " public void foo(int a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(float a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(double a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(char a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " }\n" + + " private class A {\n" + + " public void foo(int a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(float a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(boolean a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(Integer a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. WARNING in X.java (at line 2)\n" + + " public class C extends B {\n" + + " ^\n" + + "Access to enclosing constructor X.B() is emulated by a synthetic accessor method\n" + + "----------\n" + + "2. WARNING in X.java (at line 16)\n" + + " private class B extends A {\n" + + " ^\n" + + "Access to enclosing constructor X.A() is emulated by a synthetic accessor method\n" + + "----------\n" + + "3. WARNING in X.java (at line 23)\n" + + " public void foo(double a) {\n" + + " ^^^^^^^^^^^^^\n" + + "The method foo(double) from the type X.B is never used locally\n" + + "----------\n" + + "4. WARNING in X.java (at line 31)\n" + + " public void foo(int a) {\n" + + " ^^^^^^^^^^\n" + + "The method foo(int) from the type X.A is never used locally\n" + + "----------\n" + + "5. WARNING in X.java (at line 34)\n" + + " public void foo(float a) {\n" + + " ^^^^^^^^^^^^\n" + + "The method foo(float) from the type X.A is never used locally\n" + + "----------\n" + + "6. WARNING in X.java (at line 37)\n" + + " public void foo(boolean a) {\n" + + " ^^^^^^^^^^^^^^\n" + + "The method foo(boolean) from the type X.A is never used locally\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660 +// check usage via super-call +public void test099b() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " private class A {\n" + + " public void foo(int a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(float a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(boolean a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(Integer a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " }\n" + + " private class B extends A {\n" + + " public void foo(int a) {\n" + + " super.foo(a);\n" + + " }\n" + + " public void foo(float a) {\n" + + " super.foo(a);\n" + + " }\n" + + " public void foo(double a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(char a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " }\n" + + " public class C extends B {\n" + + " public void foo(int a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " public void foo(double a) {\n" + + " super.foo(a);\n" + + " }\n" + + " public void foo(boolean a) {\n" + + " super.foo(a);\n" + + " }\n" + + " public void foo(byte a) {\n" + + " System.out.println(\"Hello\");\n" + + " }\n" + + " }\n" + + "}\n" + }, + "----------\n" + + "1. WARNING in X.java (at line 16)\n" + + " private class B extends A {\n" + + " ^\n" + + "Access to enclosing constructor X.A() is emulated by a synthetic accessor method\n" + + "----------\n" + + "2. WARNING in X.java (at line 30)\n" + + " public class C extends B {\n" + + " ^\n" + + "Access to enclosing constructor X.B() is emulated by a synthetic accessor method\n" + + "----------\n"); +} +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=296660 public void test100() { this.runNegativeTest( new String[] { Index: src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java,v retrieving revision 1.26 diff -u -r1.26 ProgrammingProblemsTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java 22 Oct 2010 22:42:32 -0000 1.26 +++ src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java 23 Oct 2010 15:36:15 -0000 @@ -7,7 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation - * Stephan Herrmann - Contribution for bug 185682 - Increment/decrement operators mark local variables as read + * Stephan Herrmann - Contributions for + * bug 185682 - Increment/decrement operators mark local variables as read + * bug 328281 - visibility leaks not detected when analyzing unused field in private class *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; @@ -2120,5 +2122,30 @@ true/*shouldFlushOutputDirectory*/, customOptions); } +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=328281 +public void test0052() { + Map customOptions = getCompilerOptions(); + customOptions.put(CompilerOptions.OPTION_ReportUnusedPrivateMember, CompilerOptions.ERROR); + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " Y y = new Y();\n" + + " private class Y {\n" + + " int abc;\n" + + " Y() {\n" + + " abc++;\n" + // not a relevant usage + " }\n" + + " }\n" + + " class Z extends Y {}\n" + // makes 'abc' externally accessible + "}" + }, + "", + null/*classLibraries*/, + true/*shouldFlushOutputDirectory*/, + null/*vmArguments*/, + customOptions, + null/*requestor*/); +} } \ No newline at end of file