Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 78286 Details for
Bug 203061
[compiler] Uninitialized member variables used in nonstatic initializers of peer members don't trigger compilation error
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Proposed patch
203061.txt (text/plain), 58.63 KB, created by
Philipe Mulet
on 2007-09-13 04:50:12 EDT
(
hide
)
Description:
Proposed patch
Filename:
MIME Type:
Creator:
Philipe Mulet
Created:
2007-09-13 04:50:12 EDT
Size:
58.63 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jdt.core.tests.compiler >Index: src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java,v >retrieving revision 1.640 >diff -u -r1.640 GenericTypeTest.java >--- src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 13 Sep 2007 07:05:55 -0000 1.640 >+++ src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java 13 Sep 2007 08:49:44 -0000 >@@ -38757,7 +38757,7 @@ > } > //https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation > public void test1161() { >- this.runNegativeTest( >+ this.runConformTest( > new String[] { > "X.java", > "class Y<T extends Y<T>> {}\n" + >@@ -38770,7 +38770,7 @@ > } > //https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation > public void test1162() { >- this.runNegativeTest( >+ this.runConformTest( > new String[] { > "X.java", > "class Y<T extends Y<T>> {}\n" + >@@ -38781,4 +38781,152 @@ > }, > ""); > } >+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 - variation >+public void test1163() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public final class X<T> {\n" + >+ " private final Object mObj;\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " {\n" + >+ " Object o1 = mObj;\n" + >+ " }\n" + >+ " Object o2 = mObj;\n" + >+ " void foo() {\n" + >+ " Object o3 = mObj;\n" + >+ " }\n" + >+ " };\n" + >+ " public X() {\n" + >+ " mObj = \"\";\n" + >+ " }\n" + >+ "}\n", // ================= >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 3)\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " ^^^^^^^^^^\n" + >+ "The field X<T>.mDependent is never read locally\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "The blank final field mObj may not have been initialized\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 7)\n" + >+ " Object o2 = mObj;\n" + >+ " ^^\n" + >+ "The field new Object(){}.o2 is never read locally\n" + >+ "----------\n" + >+ "5. WARNING in X.java (at line 7)\n" + >+ " Object o2 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "6. ERROR in X.java (at line 7)\n" + >+ " Object o2 = mObj;\n" + >+ " ^^^^\n" + >+ "The blank final field mObj may not have been initialized\n" + >+ "----------\n" + >+ "7. WARNING in X.java (at line 8)\n" + >+ " void foo() {\n" + >+ " ^^^^^\n" + >+ "The method foo() from the type new Object(){} is never used locally\n" + >+ "----------\n" + >+ "8. WARNING in X.java (at line 9)\n" + >+ " Object o3 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n"); >+} >+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 - variation >+public void test1164() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public final class X<T> {\n" + >+ " private final Object mObj;\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " {\n" + >+ " Object o1 = mObj;\n" + >+ " mObj = \"1\";\n" + >+ " }\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " void foo() {\n" + >+ " Object o3 = mObj;\n" + >+ " mObj = \"3\";\n" + >+ " }\n" + >+ " };\n" + >+ " public X() {\n" + >+ " mObj = \"\";\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 3)\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " ^^^^^^^^^^\n" + >+ "The field X<T>.mDependent is never read locally\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "The blank final field mObj may not have been initialized\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 6)\n" + >+ " mObj = \"1\";\n" + >+ " ^^^^\n" + >+ "Write access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "5. ERROR in X.java (at line 6)\n" + >+ " mObj = \"1\";\n" + >+ " ^^^^\n" + >+ "The final field X<T>.mObj cannot be assigned\n" + >+ "----------\n" + >+ "6. WARNING in X.java (at line 8)\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " ^^\n" + >+ "The field new Object(){}.o2 is never read locally\n" + >+ "----------\n" + >+ "7. WARNING in X.java (at line 8)\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " ^^^^\n" + >+ "Write access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "8. ERROR in X.java (at line 8)\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " ^^^^\n" + >+ "The final field X<T>.mObj cannot be assigned\n" + >+ "----------\n" + >+ "9. WARNING in X.java (at line 9)\n" + >+ " void foo() {\n" + >+ " ^^^^^\n" + >+ "The method foo() from the type new Object(){} is never used locally\n" + >+ "----------\n" + >+ "10. WARNING in X.java (at line 10)\n" + >+ " Object o3 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "11. WARNING in X.java (at line 11)\n" + >+ " mObj = \"3\";\n" + >+ " ^^^^\n" + >+ "Write access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "12. ERROR in X.java (at line 11)\n" + >+ " mObj = \"3\";\n" + >+ " ^^^^\n" + >+ "The final field X<T>.mObj cannot be assigned\n" + >+ "----------\n"); >+} > } >#P org.eclipse.jdt.core >Index: compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java,v >retrieving revision 1.97 >diff -u -r1.97 SingleNameReference.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 2 May 2007 00:32:25 -0000 1.97 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 13 Sep 2007 08:49:47 -0000 >@@ -41,7 +41,7 @@ > case Binding.FIELD : // reading a field > FieldBinding fieldBinding; > if ((fieldBinding = (FieldBinding) binding).isBlankFinal() >- && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { >+ && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { > if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { > currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); > } >@@ -152,7 +152,7 @@ > } > } > // check if reading a final blank field >- if (fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { >+ if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { > if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { > currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); > } >Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java,v >retrieving revision 1.109 >diff -u -r1.109 FieldReference.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 15 Mar 2007 14:04:15 -0000 1.109 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 13 Sep 2007 08:49:46 -0000 >@@ -46,7 +46,7 @@ > if (isCompound) { // check the variable part is initialized if blank final > if (binding.isBlankFinal() > && receiver.isThis() >- && currentScope.allowBlankFinalFieldAssignment(binding) >+ && currentScope.needBlankFinalFieldInitializationCheck(binding) > && (!flowInfo.isDefinitelyAssigned(binding))) { > currentScope.problemReporter().uninitializedBlankFinalField(binding, this); > // we could improve error msg here telling "cannot use compound assignment on final blank field" >Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java,v >retrieving revision 1.117 >diff -u -r1.117 QualifiedNameReference.java >--- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 15 Jul 2007 00:17:22 -0000 1.117 >+++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 13 Sep 2007 08:49:46 -0000 >@@ -85,7 +85,7 @@ > // check if final blank field > if (lastFieldBinding.isBlankFinal() > && this.otherBindings != null // the last field binding is only assigned >- && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { >+ && currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)) { > if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) { > currentScope.problemReporter().uninitializedBlankFinalField( > lastFieldBinding, >@@ -134,7 +134,7 @@ > if (isCompound) { > if (otherBindingsCount == 0 > && lastFieldBinding.isBlankFinal() >- && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding) >+ && currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding) > && (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) { > currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this); > } >@@ -237,7 +237,7 @@ > } > // check if reading a final blank field > if (fieldBinding.isBlankFinal() >- && currentScope.allowBlankFinalFieldAssignment(fieldBinding) >+ && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding) > && !flowInfo.isDefinitelyAssigned(fieldBinding)) { > currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); > } >Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java,v >retrieving revision 1.65 >diff -u -r1.65 MethodScope.java >--- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java 29 Aug 2007 18:11:25 -0000 1.65 >+++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java 13 Sep 2007 08:49:47 -0000 >@@ -19,7 +19,7 @@ > import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; > > /** >- * Particular block scope used for methods, constructors or clinits, representing >+ * Specific block scope used for methods, constructors or clinits, representing > * its outermost blockscope. Note also that such a scope will be provided to enclose > * field initializers subscopes as well. > */ >@@ -49,449 +49,437 @@ > // inner-emulation > public SyntheticArgumentBinding[] extraSyntheticArguments; > >- public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) { >+public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) { >+ super(METHOD_SCOPE, parent); >+ locals = new LocalVariableBinding[5]; >+ this.referenceContext = context; >+ this.isStatic = isStatic; >+ this.startIndex = 0; >+} > >- super(METHOD_SCOPE, parent); >- locals = new LocalVariableBinding[5]; >- this.referenceContext = context; >- this.isStatic = isStatic; >- this.startIndex = 0; >- } >- >- /* Spec : 8.4.3 & 9.4 >- */ >- private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) { >- >- int modifiers = methodBinding.modifiers; >- final ReferenceBinding declaringClass = methodBinding.declaringClass; >- if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) >- problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >- >- if ((((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) != 0) { >- // certain flags are propagated from declaring class onto constructor >- final int DECLARING_FLAGS = ClassFileConstants.AccEnum|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected; >- final int VISIBILITY_FLAGS = ClassFileConstants.AccPrivate|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected; >- int flags; >- if ((flags = declaringClass.modifiers & DECLARING_FLAGS) != 0) { >- if ((flags & ClassFileConstants.AccEnum) != 0) { >- modifiers &= ~VISIBILITY_FLAGS; >- modifiers |= ClassFileConstants.AccPrivate; // default constructor is implicitly private in enum >- } else { >- modifiers &= ~VISIBILITY_FLAGS; >- modifiers |= flags; // propagate public/protected >- } >+String basicToString(int tab) { >+ String newLine = "\n"; //$NON-NLS-1$ >+ for (int i = tab; --i >= 0;) >+ newLine += "\t"; //$NON-NLS-1$ >+ >+ String s = newLine + "--- Method Scope ---"; //$NON-NLS-1$ >+ newLine += "\t"; //$NON-NLS-1$ >+ s += newLine + "locals:"; //$NON-NLS-1$ >+ for (int i = 0; i < localIndex; i++) >+ s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$ >+ s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$ >+ s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$ >+ s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$ >+ s += newLine + "lastVisibleFieldID = " + lastVisibleFieldID; //$NON-NLS-1$ >+ s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$ >+ return s; >+} >+ >+/** >+ * Spec : 8.4.3 & 9.4 >+ */ >+private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) { >+ int modifiers = methodBinding.modifiers; >+ final ReferenceBinding declaringClass = methodBinding.declaringClass; >+ if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) >+ problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ >+ if ((((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) != 0) { >+ // certain flags are propagated from declaring class onto constructor >+ final int DECLARING_FLAGS = ClassFileConstants.AccEnum|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected; >+ final int VISIBILITY_FLAGS = ClassFileConstants.AccPrivate|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected; >+ int flags; >+ if ((flags = declaringClass.modifiers & DECLARING_FLAGS) != 0) { >+ if ((flags & ClassFileConstants.AccEnum) != 0) { >+ modifiers &= ~VISIBILITY_FLAGS; >+ modifiers |= ClassFileConstants.AccPrivate; // default constructor is implicitly private in enum >+ } else { >+ modifiers &= ~VISIBILITY_FLAGS; >+ modifiers |= flags; // propagate public/protected > } > } >+ } > >- // after this point, tests on the 16 bits reserved. >- int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; >+ // after this point, tests on the 16 bits reserved. >+ int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; > >- // check for abnormal modifiers >- final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStrictfp); >- if (declaringClass.isEnum() && (((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) == 0) { >- final int UNEXPECTED_ENUM_CONSTR_MODIFIERS = ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStrictfp); >- if ((realModifiers & UNEXPECTED_ENUM_CONSTR_MODIFIERS) != 0) { >- problemReporter().illegalModifierForEnumConstructor((AbstractMethodDeclaration) referenceContext); >- modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_ENUM_CONSTR_MODIFIERS; >- } else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) { >- // must check the parse node explicitly >- problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); >- } >- modifiers |= ClassFileConstants.AccPrivate; // enum constructor is implicitly private >- } else if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { >- problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); >- modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; >+ // check for abnormal modifiers >+ final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStrictfp); >+ if (declaringClass.isEnum() && (((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) == 0) { >+ final int UNEXPECTED_ENUM_CONSTR_MODIFIERS = ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStrictfp); >+ if ((realModifiers & UNEXPECTED_ENUM_CONSTR_MODIFIERS) != 0) { >+ problemReporter().illegalModifierForEnumConstructor((AbstractMethodDeclaration) referenceContext); >+ modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_ENUM_CONSTR_MODIFIERS; > } else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) { > // must check the parse node explicitly > problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); > } >- >- // check for incompatible modifiers in the visibility bits, isolate the visibility bits >- int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); >- if ((accessorBits & (accessorBits - 1)) != 0) { >- problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >- >- // need to keep the less restrictive so disable Protected/Private as necessary >- if ((accessorBits & ClassFileConstants.AccPublic) != 0) { >- if ((accessorBits & ClassFileConstants.AccProtected) != 0) >- modifiers &= ~ClassFileConstants.AccProtected; >- if ((accessorBits & ClassFileConstants.AccPrivate) != 0) >- modifiers &= ~ClassFileConstants.AccPrivate; >- } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { >+ modifiers |= ClassFileConstants.AccPrivate; // enum constructor is implicitly private >+ } else if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { >+ problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); >+ modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; >+ } else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) { >+ // must check the parse node explicitly >+ problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); >+ } >+ >+ // check for incompatible modifiers in the visibility bits, isolate the visibility bits >+ int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); >+ if ((accessorBits & (accessorBits - 1)) != 0) { >+ problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ >+ // need to keep the less restrictive so disable Protected/Private as necessary >+ if ((accessorBits & ClassFileConstants.AccPublic) != 0) { >+ if ((accessorBits & ClassFileConstants.AccProtected) != 0) >+ modifiers &= ~ClassFileConstants.AccProtected; >+ if ((accessorBits & ClassFileConstants.AccPrivate) != 0) > modifiers &= ~ClassFileConstants.AccPrivate; >- } >+ } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { >+ modifiers &= ~ClassFileConstants.AccPrivate; > } >+ } > > // // if the receiver's declaring class is a private nested type, then make sure the receiver is not private (causes problems for inner type emulation) > // if (declaringClass.isPrivate() && (modifiers & ClassFileConstants.AccPrivate) != 0) > // modifiers &= ~ClassFileConstants.AccPrivate; > >- methodBinding.modifiers = modifiers; >- } >- >- /* Spec : 8.4.3 & 9.4 >- */ >- private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { >- >- int modifiers = methodBinding.modifiers; >- final ReferenceBinding declaringClass = methodBinding.declaringClass; >- if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) >- problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >- >- // after this point, tests on the 16 bits reserved. >- int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; >- >- // set the requested modifiers for a method in an interface/annotation >- if (declaringClass.isInterface()) { >- if ((realModifiers & ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract)) != 0) { >- if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0) >- problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) referenceContext); >- else >- problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) referenceContext); >- } >- return; >- } >- >- // check for abnormal modifiers >- final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected >- | ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp); >- if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { >- problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); >- modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; >- } >+ methodBinding.modifiers = modifiers; >+} > >- // check for incompatible modifiers in the visibility bits, isolate the visibility bits >- int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); >- if ((accessorBits & (accessorBits - 1)) != 0) { >- problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >- >- // need to keep the less restrictive so disable Protected/Private as necessary >- if ((accessorBits & ClassFileConstants.AccPublic) != 0) { >- if ((accessorBits & ClassFileConstants.AccProtected) != 0) >- modifiers &= ~ClassFileConstants.AccProtected; >- if ((accessorBits & ClassFileConstants.AccPrivate) != 0) >- modifiers &= ~ClassFileConstants.AccPrivate; >- } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { >+/** >+ * Spec : 8.4.3 & 9.4 >+ */ >+private void checkAndSetModifiersForMethod(MethodBinding methodBinding) { >+ int modifiers = methodBinding.modifiers; >+ final ReferenceBinding declaringClass = methodBinding.declaringClass; >+ if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0) >+ problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ >+ // after this point, tests on the 16 bits reserved. >+ int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag; >+ >+ // set the requested modifiers for a method in an interface/annotation >+ if (declaringClass.isInterface()) { >+ if ((realModifiers & ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract)) != 0) { >+ if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0) >+ problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) referenceContext); >+ else >+ problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) referenceContext); >+ } >+ return; >+ } >+ >+ // check for abnormal modifiers >+ final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected >+ | ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp); >+ if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) { >+ problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext); >+ modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS; >+ } >+ >+ // check for incompatible modifiers in the visibility bits, isolate the visibility bits >+ int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate); >+ if ((accessorBits & (accessorBits - 1)) != 0) { >+ problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ >+ // need to keep the less restrictive so disable Protected/Private as necessary >+ if ((accessorBits & ClassFileConstants.AccPublic) != 0) { >+ if ((accessorBits & ClassFileConstants.AccProtected) != 0) >+ modifiers &= ~ClassFileConstants.AccProtected; >+ if ((accessorBits & ClassFileConstants.AccPrivate) != 0) > modifiers &= ~ClassFileConstants.AccPrivate; >- } >+ } else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) { >+ modifiers &= ~ClassFileConstants.AccPrivate; > } >+ } > >- // check for modifiers incompatible with abstract modifier >- if ((modifiers & ClassFileConstants.AccAbstract) != 0) { >- int incompatibleWithAbstract = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp; >- if ((modifiers & incompatibleWithAbstract) != 0) >- problemReporter().illegalAbstractModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >- if (!methodBinding.declaringClass.isAbstract()) >- problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) declaringClass, (AbstractMethodDeclaration) referenceContext); >- } >- >- /* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final) >- // methods from a final class are final : 8.4.3.3 >- if (methodBinding.declaringClass.isFinal()) >- modifiers |= AccFinal; >- */ >- // native methods cannot also be tagged as strictfp >- if ((modifiers & ClassFileConstants.AccNative) != 0 && (modifiers & ClassFileConstants.AccStrictfp) != 0) >- problemReporter().nativeMethodsCannotBeStrictfp(declaringClass, (AbstractMethodDeclaration) referenceContext); >- >- // static members are only authorized in a static member or top level type >- if (((realModifiers & ClassFileConstants.AccStatic) != 0) && declaringClass.isNestedType() && !declaringClass.isStatic()) >- problemReporter().unexpectedStaticModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >- >- methodBinding.modifiers = modifiers; >+ // check for modifiers incompatible with abstract modifier >+ if ((modifiers & ClassFileConstants.AccAbstract) != 0) { >+ int incompatibleWithAbstract = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp; >+ if ((modifiers & incompatibleWithAbstract) != 0) >+ problemReporter().illegalAbstractModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ if (!methodBinding.declaringClass.isAbstract()) >+ problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) declaringClass, (AbstractMethodDeclaration) referenceContext); > } >- >- /* Compute variable positions in scopes given an initial position offset >- * ignoring unused local variables. >- * >- * Deal with arguments here, locals and subscopes are processed in BlockScope method >- */ >- public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) { >- >- boolean isReportingUnusedArgument = false; >- >- if (referenceContext instanceof AbstractMethodDeclaration) { >- AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)referenceContext; >- MethodBinding method = methodDecl.binding; >- if (!(method.isAbstract() >- || (method.isImplementing() && !compilerOptions().reportUnusedParameterWhenImplementingAbstract) >- || (method.isOverriding() && !method.isImplementing() && !compilerOptions().reportUnusedParameterWhenOverridingConcrete) >- || method.isMain())) { >- isReportingUnusedArgument = true; >- } >+ >+ /* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final) >+ // methods from a final class are final : 8.4.3.3 >+ if (methodBinding.declaringClass.isFinal()) >+ modifiers |= AccFinal; >+ */ >+ // native methods cannot also be tagged as strictfp >+ if ((modifiers & ClassFileConstants.AccNative) != 0 && (modifiers & ClassFileConstants.AccStrictfp) != 0) >+ problemReporter().nativeMethodsCannotBeStrictfp(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ >+ // static members are only authorized in a static member or top level type >+ if (((realModifiers & ClassFileConstants.AccStatic) != 0) && declaringClass.isNestedType() && !declaringClass.isStatic()) >+ problemReporter().unexpectedStaticModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext); >+ >+ methodBinding.modifiers = modifiers; >+} >+ >+/** >+ * Compute variable positions in scopes given an initial position offset >+ * ignoring unused local variables. >+ * >+ * Deal with arguments here, locals and subscopes are processed in BlockScope method >+ */ >+public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) { >+ >+ boolean isReportingUnusedArgument = false; >+ >+ if (referenceContext instanceof AbstractMethodDeclaration) { >+ AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)referenceContext; >+ MethodBinding method = methodDecl.binding; >+ if (!(method.isAbstract() >+ || (method.isImplementing() && !compilerOptions().reportUnusedParameterWhenImplementingAbstract) >+ || (method.isOverriding() && !method.isImplementing() && !compilerOptions().reportUnusedParameterWhenOverridingConcrete) >+ || method.isMain())) { >+ isReportingUnusedArgument = true; > } >- this.offset = initOffset; >- this.maxOffset = initOffset; >+ } >+ this.offset = initOffset; >+ this.maxOffset = initOffset; > >- // manage arguments >- int ilocal = 0, maxLocals = this.localIndex; >- while (ilocal < maxLocals) { >- LocalVariableBinding local = locals[ilocal]; >- if (local == null || ((local.tagBits & TagBits.IsArgument) == 0)) break; // done with arguments >- >- // do not report fake used variable >- if (isReportingUnusedArgument >- && local.useFlag == LocalVariableBinding.UNUSED >- && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable >- this.problemReporter().unusedArgument(local.declaration); >- } >+ // manage arguments >+ int ilocal = 0, maxLocals = this.localIndex; >+ while (ilocal < maxLocals) { >+ LocalVariableBinding local = locals[ilocal]; >+ if (local == null || ((local.tagBits & TagBits.IsArgument) == 0)) break; // done with arguments >+ >+ // do not report fake used variable >+ if (isReportingUnusedArgument >+ && local.useFlag == LocalVariableBinding.UNUSED >+ && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable >+ this.problemReporter().unusedArgument(local.declaration); >+ } > >- // record user-defined argument for attribute generation >- codeStream.record(local); >+ // record user-defined argument for attribute generation >+ codeStream.record(local); > >- // assign variable position >- local.resolvedPosition = this.offset; >+ // assign variable position >+ local.resolvedPosition = this.offset; > >- if ((local.type == TypeBinding.LONG) || (local.type == TypeBinding.DOUBLE)) { >+ if ((local.type == TypeBinding.LONG) || (local.type == TypeBinding.DOUBLE)) { >+ this.offset += 2; >+ } else { >+ this.offset++; >+ } >+ // check for too many arguments/local variables >+ if (this.offset > 0xFF) { // no more than 255 words of arguments >+ this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration); >+ } >+ ilocal++; >+ } >+ >+ // sneak in extra argument before other local variables >+ if (extraSyntheticArguments != null) { >+ for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg < maxArguments; iarg++){ >+ SyntheticArgumentBinding argument = extraSyntheticArguments[iarg]; >+ argument.resolvedPosition = this.offset; >+ if ((argument.type == TypeBinding.LONG) || (argument.type == TypeBinding.DOUBLE)){ > this.offset += 2; > } else { > this.offset++; > } >- // check for too many arguments/local variables > if (this.offset > 0xFF) { // no more than 255 words of arguments >- this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration); >+ this.problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); > } >- ilocal++; > } >- >- // sneak in extra argument before other local variables >- if (extraSyntheticArguments != null) { >- for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg < maxArguments; iarg++){ >- SyntheticArgumentBinding argument = extraSyntheticArguments[iarg]; >- argument.resolvedPosition = this.offset; >- if ((argument.type == TypeBinding.LONG) || (argument.type == TypeBinding.DOUBLE)){ >- this.offset += 2; >- } else { >- this.offset++; >- } >- if (this.offset > 0xFF) { // no more than 255 words of arguments >- this.problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); >- } >- } >- } >- this.computeLocalVariablePositions(ilocal, this.offset, codeStream); > } >+ this.computeLocalVariablePositions(ilocal, this.offset, codeStream); >+} > >- /* Error management: >- * keep null for all the errors that prevent the method to be created >- * otherwise return a correct method binding (but without the element >- * that caused the problem) : ie : Incorrect thrown exception >- */ >- MethodBinding createMethod(AbstractMethodDeclaration method) { >- >- // is necessary to ensure error reporting >- this.referenceContext = method; >- method.scope = this; >- SourceTypeBinding declaringClass = referenceType().binding; >- int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved; >- if (method.isConstructor()) { >- if (method.isDefaultConstructor()) >- modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor; >- method.binding = new MethodBinding(modifiers, null, null, declaringClass); >- checkAndSetModifiersForConstructor(method.binding); >- } else { >- if (declaringClass.isInterface()) // interface or annotation type >- modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; >- method.binding = >- new MethodBinding(modifiers, method.selector, null, null, null, declaringClass); >- checkAndSetModifiersForMethod(method.binding); >- } >- this.isStatic = method.binding.isStatic(); >- >- Argument[] argTypes = method.arguments; >- int argLength = argTypes == null ? 0 : argTypes.length; >- if (argLength > 0 && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { >- if (argTypes[--argLength].isVarArgs()) >- method.binding.modifiers |= ClassFileConstants.AccVarargs; >- while (--argLength >= 0) { >- if (argTypes[argLength].isVarArgs()) >- problemReporter().illegalVararg(argTypes[argLength], method); >- } >- } >- >- TypeParameter[] typeParameters = method.typeParameters(); >- // do not construct type variables if source < 1.5 >- if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) { >- method.binding.typeVariables = Binding.NO_TYPE_VARIABLES; >- } else { >- method.binding.typeVariables = createTypeVariables(typeParameters, method.binding); >- method.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature; >+/** >+ * Error management: >+ * keep null for all the errors that prevent the method to be created >+ * otherwise return a correct method binding (but without the element >+ * that caused the problem) : ie : Incorrect thrown exception >+ */ >+MethodBinding createMethod(AbstractMethodDeclaration method) { >+ // is necessary to ensure error reporting >+ this.referenceContext = method; >+ method.scope = this; >+ SourceTypeBinding declaringClass = referenceType().binding; >+ int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved; >+ if (method.isConstructor()) { >+ if (method.isDefaultConstructor()) >+ modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor; >+ method.binding = new MethodBinding(modifiers, null, null, declaringClass); >+ checkAndSetModifiersForConstructor(method.binding); >+ } else { >+ if (declaringClass.isInterface()) // interface or annotation type >+ modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; >+ method.binding = >+ new MethodBinding(modifiers, method.selector, null, null, null, declaringClass); >+ checkAndSetModifiersForMethod(method.binding); >+ } >+ this.isStatic = method.binding.isStatic(); >+ >+ Argument[] argTypes = method.arguments; >+ int argLength = argTypes == null ? 0 : argTypes.length; >+ if (argLength > 0 && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { >+ if (argTypes[--argLength].isVarArgs()) >+ method.binding.modifiers |= ClassFileConstants.AccVarargs; >+ while (--argLength >= 0) { >+ if (argTypes[argLength].isVarArgs()) >+ problemReporter().illegalVararg(argTypes[argLength], method); > } >- return method.binding; > } >- >- /* Overridden to detect the error case inside an explicit constructor call: > >- class X { >- int i; >- X myX; >- X(X x) { >- this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors >- } >+ TypeParameter[] typeParameters = method.typeParameters(); >+ // do not construct type variables if source < 1.5 >+ if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) { >+ method.binding.typeVariables = Binding.NO_TYPE_VARIABLES; >+ } else { >+ method.binding.typeVariables = createTypeVariables(typeParameters, method.binding); >+ method.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature; > } >- */ >- public FieldBinding findField( >- TypeBinding receiverType, >- char[] fieldName, >- InvocationSite invocationSite, >- boolean needResolve) { >- >- FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve); >- if (field == null) >- return null; >- if (!field.isValidBinding()) >- return field; // answer the error field >- if (field.isStatic()) >- return field; // static fields are always accessible >+ return method.binding; >+} > >- if (!isConstructorCall || receiverType != enclosingSourceType()) >- return field; >+/** >+ * Overridden to detect the error case inside an explicit constructor call: >+class X { >+ int i; >+ X myX; >+ X(X x) { >+ this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors >+ } >+} >+ */ >+public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) { >+ >+ FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve); >+ if (field == null) >+ return null; >+ if (!field.isValidBinding()) >+ return field; // answer the error field >+ if (field.isStatic()) >+ return field; // static fields are always accessible >+ >+ if (!isConstructorCall || receiverType != enclosingSourceType()) >+ return field; > >- if (invocationSite instanceof SingleNameReference) >+ if (invocationSite instanceof SingleNameReference) >+ return new ProblemFieldBinding( >+ field, // closest match >+ field.declaringClass, >+ fieldName, >+ ProblemReasons.NonStaticReferenceInConstructorInvocation); >+ if (invocationSite instanceof QualifiedNameReference) { >+ // look to see if the field is the first binding >+ QualifiedNameReference name = (QualifiedNameReference) invocationSite; >+ if (name.binding == null) >+ // only true when the field is the fieldbinding at the beginning of name's tokens > return new ProblemFieldBinding( > field, // closest match > field.declaringClass, > fieldName, > ProblemReasons.NonStaticReferenceInConstructorInvocation); >- if (invocationSite instanceof QualifiedNameReference) { >- // look to see if the field is the first binding >- QualifiedNameReference name = (QualifiedNameReference) invocationSite; >- if (name.binding == null) >- // only true when the field is the fieldbinding at the beginning of name's tokens >- return new ProblemFieldBinding( >- field, // closest match >- field.declaringClass, >- fieldName, >- ProblemReasons.NonStaticReferenceInConstructorInvocation); >- } >- return field; >- } >- >- public boolean isInsideConstructor() { >- >- return (referenceContext instanceof ConstructorDeclaration); >- } >- >- public boolean isInsideInitializer() { >- >- return (referenceContext instanceof TypeDeclaration); > } >+ return field; >+} > >- public boolean isInsideInitializerOrConstructor() { >+public boolean isInsideConstructor() { >+ return (referenceContext instanceof ConstructorDeclaration); >+} > >- return (referenceContext instanceof TypeDeclaration) >- || (referenceContext instanceof ConstructorDeclaration); >- } >+public boolean isInsideInitializer() { >+ return (referenceContext instanceof TypeDeclaration); >+} > >- /* Answer the problem reporter to use for raising new problems. >- * >- * Note that as a side-effect, this updates the current reference context >- * (unit, type or method) in case the problem handler decides it is necessary >- * to abort. >- */ >- public ProblemReporter problemReporter() { >+public boolean isInsideInitializerOrConstructor() { >+ return (referenceContext instanceof TypeDeclaration) >+ || (referenceContext instanceof ConstructorDeclaration); >+} > >- MethodScope outerMethodScope; >- if ((outerMethodScope = outerMostMethodScope()) == this) { >- ProblemReporter problemReporter = referenceCompilationUnit().problemReporter; >- problemReporter.referenceContext = referenceContext; >- return problemReporter; >- } >- return outerMethodScope.problemReporter(); >+/** >+ * Answer the problem reporter to use for raising new problems. >+ * >+ * Note that as a side-effect, this updates the current reference context >+ * (unit, type or method) in case the problem handler decides it is necessary >+ * to abort. >+ */ >+public ProblemReporter problemReporter() { >+ MethodScope outerMethodScope; >+ if ((outerMethodScope = outerMostMethodScope()) == this) { >+ ProblemReporter problemReporter = referenceCompilationUnit().problemReporter; >+ problemReporter.referenceContext = referenceContext; >+ return problemReporter; > } >+ return outerMethodScope.problemReporter(); >+} > >- public final int recordInitializationStates(FlowInfo flowInfo) { >- >- if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return -1; >- >- UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInitsWithoutSideEffect(); >- long[] extraInits = unconditionalFlowInfo.extra == null ? >- null : unconditionalFlowInfo.extra[0]; >- long inits = unconditionalFlowInfo.definiteInits; >- checkNextEntry : for (int i = lastIndex; --i >= 0;) { >- if (definiteInits[i] == inits) { >- long[] otherInits = extraDefiniteInits[i]; >- if ((extraInits != null) && (otherInits != null)) { >- if (extraInits.length == otherInits.length) { >- int j, max; >- for (j = 0, max = extraInits.length; j < max; j++) { >- if (extraInits[j] != otherInits[j]) { >- continue checkNextEntry; >- } >+public final int recordInitializationStates(FlowInfo flowInfo) { >+ if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return -1; >+ UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInitsWithoutSideEffect(); >+ long[] extraInits = unconditionalFlowInfo.extra == null ? >+ null : unconditionalFlowInfo.extra[0]; >+ long inits = unconditionalFlowInfo.definiteInits; >+ checkNextEntry : for (int i = lastIndex; --i >= 0;) { >+ if (definiteInits[i] == inits) { >+ long[] otherInits = extraDefiniteInits[i]; >+ if ((extraInits != null) && (otherInits != null)) { >+ if (extraInits.length == otherInits.length) { >+ int j, max; >+ for (j = 0, max = extraInits.length; j < max; j++) { >+ if (extraInits[j] != otherInits[j]) { >+ continue checkNextEntry; > } >- return i; >- } >- } else { >- if ((extraInits == null) && (otherInits == null)) { >- return i; > } >+ return i; >+ } >+ } else { >+ if ((extraInits == null) && (otherInits == null)) { >+ return i; > } > } > } >- >- // add a new entry >- if (definiteInits.length == lastIndex) { >- // need a resize >- System.arraycopy( >- definiteInits, >- 0, >- (definiteInits = new long[lastIndex + 20]), >- 0, >- lastIndex); >- System.arraycopy( >- extraDefiniteInits, >- 0, >- (extraDefiniteInits = new long[lastIndex + 20][]), >- 0, >- lastIndex); >- } >- definiteInits[lastIndex] = inits; >- if (extraInits != null) { >- extraDefiniteInits[lastIndex] = new long[extraInits.length]; >- System.arraycopy( >- extraInits, >- 0, >- extraDefiniteInits[lastIndex], >- 0, >- extraInits.length); >- } >- return lastIndex++; >- } >- >- /* Answer the reference method of this scope, or null if initialization scoope. >- */ >- public AbstractMethodDeclaration referenceMethod() { >- >- if (referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) referenceContext; >- return null; > } > >- /* Answer the reference type of this scope. >- * >- * It is the nearest enclosing type of this scope. >- */ >- public TypeDeclaration referenceType() { >- >- return ((ClassScope) parent).referenceContext; >+ // add a new entry >+ if (definiteInits.length == lastIndex) { >+ // need a resize >+ System.arraycopy( >+ definiteInits, >+ 0, >+ (definiteInits = new long[lastIndex + 20]), >+ 0, >+ lastIndex); >+ System.arraycopy( >+ extraDefiniteInits, >+ 0, >+ (extraDefiniteInits = new long[lastIndex + 20][]), >+ 0, >+ lastIndex); >+ } >+ definiteInits[lastIndex] = inits; >+ if (extraInits != null) { >+ extraDefiniteInits[lastIndex] = new long[extraInits.length]; >+ System.arraycopy( >+ extraInits, >+ 0, >+ extraDefiniteInits[lastIndex], >+ 0, >+ extraInits.length); > } >+ return lastIndex++; >+} > >- String basicToString(int tab) { >- >- String newLine = "\n"; //$NON-NLS-1$ >- for (int i = tab; --i >= 0;) >- newLine += "\t"; //$NON-NLS-1$ >- >- String s = newLine + "--- Method Scope ---"; //$NON-NLS-1$ >- newLine += "\t"; //$NON-NLS-1$ >- s += newLine + "locals:"; //$NON-NLS-1$ >- for (int i = 0; i < localIndex; i++) >- s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$ >- s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$ >- s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$ >- s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$ >- s += newLine + "lastVisibleFieldID = " + lastVisibleFieldID; //$NON-NLS-1$ >- s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$ >- return s; >- } >+/** >+ * Answer the reference method of this scope, or null if initialization scoope. >+ */ >+public AbstractMethodDeclaration referenceMethod() { >+ if (referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) referenceContext; >+ return null; >+} > >+/** >+ * Answer the reference type of this scope. >+ * It is the nearest enclosing type of this scope. >+ */ >+public TypeDeclaration referenceType() { >+ return ((ClassScope) parent).referenceContext; >+} > } >Index: compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java,v >retrieving revision 1.106 >diff -u -r1.106 BlockScope.java >--- compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 6 Mar 2007 02:38:50 -0000 1.106 >+++ compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java 13 Sep 2007 08:49:47 -0000 >@@ -111,8 +111,8 @@ > this.subscopes[this.subscopeCount++] = childScope; > } > >-/* Answer true if the receiver is suitable for assigning final blank fields. >- * >+/** >+ * Answer true if the receiver is suitable for assigning final blank fields. > * in other words, it is inside an initializer, a constructor or a clinit > */ > public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) { >@@ -125,6 +125,7 @@ > return methodScope.isInsideInitializer() // inside initializer > || ((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod(); // inside constructor or clinit > } >+ > String basicToString(int tab) { > String newLine = "\n"; //$NON-NLS-1$ > for (int i = tab; --i >= 0;) >@@ -822,6 +823,30 @@ > return max; > } > >+/** >+ * Returns true if the context requires to check initialization of final blank fields. >+ * in other words, it is inside an initializer, a constructor or a clinit >+ */ >+public final boolean needBlankFinalFieldInitializationCheck(FieldBinding binding) { >+ boolean isStatic = binding.isStatic(); >+ ReferenceBinding fieldDeclaringClass = binding.declaringClass; >+ // loop in enclosing context, until reaching the field declaring context >+ MethodScope methodScope = methodScope(); >+ while (methodScope != null) { >+ if (methodScope.isStatic != isStatic) >+ return false; >+ if (!methodScope.isInsideInitializer() // inside initializer >+ && !((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod()) { // inside constructor or clinit >+ return false; // found some non-initializer context >+ } >+ if (fieldDeclaringClass == methodScope.enclosingReceiverType()) { >+ return true; // found the field context, no need to check any further >+ } >+ methodScope = methodScope.enclosingMethodScope(); >+ } >+ return false; >+} >+ > /* Answer the problem reporter to use for raising new problems. > * > * Note that as a side-effect, this updates the current reference context >Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java,v >retrieving revision 1.47 >diff -u -r1.47 CodeSnippetSingleNameReference.java >--- eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java 29 Mar 2006 02:57:52 -0000 1.47 >+++ eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java 13 Sep 2007 08:49:47 -0000 >@@ -56,7 +56,7 @@ > // check if reading a final blank field > FieldBinding fieldBinding; > if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() >- && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { >+ && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) { > if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { > currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); > } >#P org.eclipse.jdt.core.tests >Index: Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java >=================================================================== >RCS file: /home/cvs/numbat/org.eclipse.jdt.core.tests/Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java,v >retrieving revision 1.106 >diff -u -r1.106 InitializationTest.java >--- Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java 15 Mar 2007 14:04:34 -0000 1.106 >+++ Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java 13 Sep 2007 08:49:51 -0000 >@@ -5473,6 +5473,154 @@ > assertTrue(false); > } > } >+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 >+public void test192() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public final class X {\n" + >+ " private final Object mObj;\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " {\n" + >+ " Object o1 = mObj;\n" + >+ " }\n" + >+ " Object o2 = mObj;\n" + >+ " void foo() {\n" + >+ " Object o3 = mObj;\n" + >+ " }\n" + >+ " };\n" + >+ " public X() {\n" + >+ " mObj = \"\";\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 3)\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " ^^^^^^^^^^\n" + >+ "The field X.mDependent is never read locally\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "The blank final field mObj may not have been initialized\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 7)\n" + >+ " Object o2 = mObj;\n" + >+ " ^^\n" + >+ "The field new Object(){}.o2 is never read locally\n" + >+ "----------\n" + >+ "5. WARNING in X.java (at line 7)\n" + >+ " Object o2 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "6. ERROR in X.java (at line 7)\n" + >+ " Object o2 = mObj;\n" + >+ " ^^^^\n" + >+ "The blank final field mObj may not have been initialized\n" + >+ "----------\n" + >+ "7. WARNING in X.java (at line 8)\n" + >+ " void foo() {\n" + >+ " ^^^^^\n" + >+ "The method foo() from the type new Object(){} is never used locally\n" + >+ "----------\n" + >+ "8. WARNING in X.java (at line 9)\n" + >+ " Object o3 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n"); >+} >+//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 - variation >+public void test193() { >+ this.runNegativeTest( >+ new String[] { >+ "X.java", >+ "public final class X {\n" + >+ " private final Object mObj;\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " {\n" + >+ " Object o1 = mObj;\n" + >+ " mObj = \"1\";\n" + >+ " }\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " void foo() {\n" + >+ " Object o3 = mObj;\n" + >+ " mObj = \"3\";\n" + >+ " }\n" + >+ " };\n" + >+ " public X() {\n" + >+ " mObj = \"\";\n" + >+ " }\n" + >+ "}\n" >+ }, >+ "----------\n" + >+ "1. WARNING in X.java (at line 3)\n" + >+ " private final Object mDependent = new Object() {\n" + >+ " ^^^^^^^^^^\n" + >+ "The field X.mDependent is never read locally\n" + >+ "----------\n" + >+ "2. WARNING in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "3. ERROR in X.java (at line 5)\n" + >+ " Object o1 = mObj;\n" + >+ " ^^^^\n" + >+ "The blank final field mObj may not have been initialized\n" + >+ "----------\n" + >+ "4. WARNING in X.java (at line 6)\n" + >+ " mObj = \"1\";\n" + >+ " ^^^^\n" + >+ "Write access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "5. ERROR in X.java (at line 6)\n" + >+ " mObj = \"1\";\n" + >+ " ^^^^\n" + >+ "The final field X.mObj cannot be assigned\n" + >+ "----------\n" + >+ "6. WARNING in X.java (at line 8)\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " ^^\n" + >+ "The field new Object(){}.o2 is never read locally\n" + >+ "----------\n" + >+ "7. WARNING in X.java (at line 8)\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " ^^^^\n" + >+ "Write access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "8. ERROR in X.java (at line 8)\n" + >+ " Object o2 = mObj = \"2\";\n" + >+ " ^^^^\n" + >+ "The final field X.mObj cannot be assigned\n" + >+ "----------\n" + >+ "9. WARNING in X.java (at line 9)\n" + >+ " void foo() {\n" + >+ " ^^^^^\n" + >+ "The method foo() from the type new Object(){} is never used locally\n" + >+ "----------\n" + >+ "10. WARNING in X.java (at line 10)\n" + >+ " Object o3 = mObj;\n" + >+ " ^^^^\n" + >+ "Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "11. WARNING in X.java (at line 11)\n" + >+ " mObj = \"3\";\n" + >+ " ^^^^\n" + >+ "Write access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + >+ "----------\n" + >+ "12. ERROR in X.java (at line 11)\n" + >+ " mObj = \"3\";\n" + >+ " ^^^^\n" + >+ "The final field X.mObj cannot be assigned\n" + >+ "----------\n"); >+} > public static Class testClass() { > return InitializationTest.class; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 203061
: 78286 |
78296