View | Details | Raw Unified | Return to bug 203061 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java (-2 / +150 lines)
Lines 38757-38763 Link Here
38757
}
38757
}
38758
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
38758
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
38759
public void test1161() {
38759
public void test1161() {
38760
	this.runNegativeTest(
38760
	this.runConformTest(
38761
		new String[] {
38761
		new String[] {
38762
			"X.java",
38762
			"X.java",
38763
			"class Y<T extends Y<T>> {}\n" + 
38763
			"class Y<T extends Y<T>> {}\n" + 
Lines 38770-38776 Link Here
38770
}
38770
}
38771
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
38771
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=202404 - variation
38772
public void test1162() {
38772
public void test1162() {
38773
	this.runNegativeTest(
38773
	this.runConformTest(
38774
		new String[] {
38774
		new String[] {
38775
			"X.java",
38775
			"X.java",
38776
			"class Y<T extends Y<T>> {}\n" + 
38776
			"class Y<T extends Y<T>> {}\n" + 
Lines 38781-38784 Link Here
38781
		},
38781
		},
38782
		"");
38782
		"");
38783
}
38783
}
38784
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 - variation
38785
public void test1163() {
38786
	this.runNegativeTest(
38787
		new String[] {
38788
			"X.java",
38789
			"public final class X<T> {\n" + 
38790
			"	private final Object mObj;\n" + 
38791
			"	private final Object mDependent = new Object() {\n" + 
38792
			"		{\n" + 
38793
			"			Object o1 = mObj;\n" + 
38794
			"		}\n" + 
38795
			"		Object o2 = mObj;\n" + 
38796
			"		void foo() {\n" + 
38797
			"			Object o3 = mObj;\n" + 
38798
			"		}\n" + 
38799
			"	};\n" + 
38800
			"	public X() {\n" + 
38801
			"		mObj = \"\";\n" + 
38802
			"	}\n" + 
38803
			"}\n", // =================
38804
		},
38805
		"----------\n" + 
38806
		"1. WARNING in X.java (at line 3)\n" + 
38807
		"	private final Object mDependent = new Object() {\n" + 
38808
		"	                     ^^^^^^^^^^\n" + 
38809
		"The field X<T>.mDependent is never read locally\n" + 
38810
		"----------\n" + 
38811
		"2. WARNING in X.java (at line 5)\n" + 
38812
		"	Object o1 = mObj;\n" + 
38813
		"	            ^^^^\n" + 
38814
		"Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38815
		"----------\n" + 
38816
		"3. ERROR in X.java (at line 5)\n" + 
38817
		"	Object o1 = mObj;\n" + 
38818
		"	            ^^^^\n" + 
38819
		"The blank final field mObj may not have been initialized\n" + 
38820
		"----------\n" + 
38821
		"4. WARNING in X.java (at line 7)\n" + 
38822
		"	Object o2 = mObj;\n" + 
38823
		"	       ^^\n" + 
38824
		"The field new Object(){}.o2 is never read locally\n" + 
38825
		"----------\n" + 
38826
		"5. WARNING in X.java (at line 7)\n" + 
38827
		"	Object o2 = mObj;\n" + 
38828
		"	            ^^^^\n" + 
38829
		"Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38830
		"----------\n" + 
38831
		"6. ERROR in X.java (at line 7)\n" + 
38832
		"	Object o2 = mObj;\n" + 
38833
		"	            ^^^^\n" + 
38834
		"The blank final field mObj may not have been initialized\n" + 
38835
		"----------\n" + 
38836
		"7. WARNING in X.java (at line 8)\n" + 
38837
		"	void foo() {\n" + 
38838
		"	     ^^^^^\n" + 
38839
		"The method foo() from the type new Object(){} is never used locally\n" + 
38840
		"----------\n" + 
38841
		"8. WARNING in X.java (at line 9)\n" + 
38842
		"	Object o3 = mObj;\n" + 
38843
		"	            ^^^^\n" + 
38844
		"Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38845
		"----------\n");
38846
}
38847
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 - variation
38848
public void test1164() {
38849
	this.runNegativeTest(
38850
		new String[] {
38851
			"X.java",
38852
			"public final class X<T> {\n" + 
38853
			"	private final Object mObj;\n" + 
38854
			"	private final Object mDependent = new Object() {\n" + 
38855
			"		{\n" + 
38856
			"			Object o1 = mObj;\n" + 
38857
			"			mObj = \"1\";\n" + 
38858
			"		}\n" + 
38859
			"		Object o2 = mObj = \"2\";\n" + 
38860
			"		void foo() {\n" + 
38861
			"			Object o3 = mObj;\n" + 
38862
			"			mObj = \"3\";\n" + 
38863
			"		}\n" + 
38864
			"	};\n" + 
38865
			"	public X() {\n" + 
38866
			"		mObj = \"\";\n" + 
38867
			"	}\n" + 
38868
			"}\n"
38869
		}, 
38870
		"----------\n" + 
38871
		"1. WARNING in X.java (at line 3)\n" + 
38872
		"	private final Object mDependent = new Object() {\n" + 
38873
		"	                     ^^^^^^^^^^\n" + 
38874
		"The field X<T>.mDependent is never read locally\n" + 
38875
		"----------\n" + 
38876
		"2. WARNING in X.java (at line 5)\n" + 
38877
		"	Object o1 = mObj;\n" + 
38878
		"	            ^^^^\n" + 
38879
		"Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38880
		"----------\n" + 
38881
		"3. ERROR in X.java (at line 5)\n" + 
38882
		"	Object o1 = mObj;\n" + 
38883
		"	            ^^^^\n" + 
38884
		"The blank final field mObj may not have been initialized\n" + 
38885
		"----------\n" + 
38886
		"4. WARNING in X.java (at line 6)\n" + 
38887
		"	mObj = \"1\";\n" + 
38888
		"	^^^^\n" + 
38889
		"Write access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38890
		"----------\n" + 
38891
		"5. ERROR in X.java (at line 6)\n" + 
38892
		"	mObj = \"1\";\n" + 
38893
		"	^^^^\n" + 
38894
		"The final field X<T>.mObj cannot be assigned\n" + 
38895
		"----------\n" + 
38896
		"6. WARNING in X.java (at line 8)\n" + 
38897
		"	Object o2 = mObj = \"2\";\n" + 
38898
		"	       ^^\n" + 
38899
		"The field new Object(){}.o2 is never read locally\n" + 
38900
		"----------\n" + 
38901
		"7. WARNING in X.java (at line 8)\n" + 
38902
		"	Object o2 = mObj = \"2\";\n" + 
38903
		"	            ^^^^\n" + 
38904
		"Write access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38905
		"----------\n" + 
38906
		"8. ERROR in X.java (at line 8)\n" + 
38907
		"	Object o2 = mObj = \"2\";\n" + 
38908
		"	            ^^^^\n" + 
38909
		"The final field X<T>.mObj cannot be assigned\n" + 
38910
		"----------\n" + 
38911
		"9. WARNING in X.java (at line 9)\n" + 
38912
		"	void foo() {\n" + 
38913
		"	     ^^^^^\n" + 
38914
		"The method foo() from the type new Object(){} is never used locally\n" + 
38915
		"----------\n" + 
38916
		"10. WARNING in X.java (at line 10)\n" + 
38917
		"	Object o3 = mObj;\n" + 
38918
		"	            ^^^^\n" + 
38919
		"Read access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38920
		"----------\n" + 
38921
		"11. WARNING in X.java (at line 11)\n" + 
38922
		"	mObj = \"3\";\n" + 
38923
		"	^^^^\n" + 
38924
		"Write access to enclosing field X<T>.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
38925
		"----------\n" + 
38926
		"12. ERROR in X.java (at line 11)\n" + 
38927
		"	mObj = \"3\";\n" + 
38928
		"	^^^^\n" + 
38929
		"The final field X<T>.mObj cannot be assigned\n" + 
38930
		"----------\n");
38931
}
38784
}
38932
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java (-2 / +2 lines)
Lines 41-47 Link Here
41
				case Binding.FIELD : // reading a field
41
				case Binding.FIELD : // reading a field
42
					FieldBinding fieldBinding;
42
					FieldBinding fieldBinding;
43
					if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
43
					if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
44
							&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
44
							&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
45
						if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
45
						if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
46
							currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
46
							currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
47
						}
47
						}
Lines 152-158 Link Here
152
					}
152
					}
153
				}				
153
				}				
154
				// check if reading a final blank field
154
				// check if reading a final blank field
155
				if (fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
155
				if (fieldBinding.isBlankFinal() && currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
156
					if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
156
					if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
157
						currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
157
						currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
158
					}
158
					}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java (-1 / +1 lines)
Lines 46-52 Link Here
46
	if (isCompound) { // check the variable part is initialized if blank final
46
	if (isCompound) { // check the variable part is initialized if blank final
47
		if (binding.isBlankFinal()
47
		if (binding.isBlankFinal()
48
			&& receiver.isThis()
48
			&& receiver.isThis()
49
			&& currentScope.allowBlankFinalFieldAssignment(binding)
49
			&& currentScope.needBlankFinalFieldInitializationCheck(binding)
50
			&& (!flowInfo.isDefinitelyAssigned(binding))) {
50
			&& (!flowInfo.isDefinitelyAssigned(binding))) {
51
			currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
51
			currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
52
			// we could improve error msg here telling "cannot use compound assignment on final blank field"
52
			// we could improve error msg here telling "cannot use compound assignment on final blank field"
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-3 / +3 lines)
Lines 85-91 Link Here
85
			// check if final blank field
85
			// check if final blank field
86
			if (lastFieldBinding.isBlankFinal()
86
			if (lastFieldBinding.isBlankFinal()
87
				    && this.otherBindings != null // the last field binding is only assigned
87
				    && this.otherBindings != null // the last field binding is only assigned
88
	 				&& currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) {
88
	 				&& currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)) {
89
				if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) {
89
				if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) {
90
					currentScope.problemReporter().uninitializedBlankFinalField(
90
					currentScope.problemReporter().uninitializedBlankFinalField(
91
						lastFieldBinding,
91
						lastFieldBinding,
Lines 134-140 Link Here
134
	if (isCompound) {
134
	if (isCompound) {
135
		if (otherBindingsCount == 0
135
		if (otherBindingsCount == 0
136
				&& lastFieldBinding.isBlankFinal()
136
				&& lastFieldBinding.isBlankFinal()
137
				&& currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)
137
				&& currentScope.needBlankFinalFieldInitializationCheck(lastFieldBinding)
138
				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
138
				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
139
			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
139
			currentScope.problemReporter().uninitializedBlankFinalField(lastFieldBinding, this);
140
		}
140
		}
Lines 237-243 Link Here
237
				}				
237
				}				
238
				// check if reading a final blank field
238
				// check if reading a final blank field
239
				if (fieldBinding.isBlankFinal()
239
				if (fieldBinding.isBlankFinal()
240
						&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)
240
						&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)
241
						&& !flowInfo.isDefinitelyAssigned(fieldBinding)) {
241
						&& !flowInfo.isDefinitelyAssigned(fieldBinding)) {
242
					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
242
					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
243
				}
243
				}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java (-383 / +371 lines)
Lines 19-25 Link Here
19
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
19
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
20
20
21
/**
21
/**
22
 * Particular block scope used for methods, constructors or clinits, representing
22
 * Specific block scope used for methods, constructors or clinits, representing
23
 * its outermost blockscope. Note also that such a scope will be provided to enclose
23
 * its outermost blockscope. Note also that such a scope will be provided to enclose
24
 * field initializers subscopes as well.
24
 * field initializers subscopes as well.
25
 */
25
 */
Lines 49-497 Link Here
49
	// inner-emulation
49
	// inner-emulation
50
	public SyntheticArgumentBinding[] extraSyntheticArguments;
50
	public SyntheticArgumentBinding[] extraSyntheticArguments;
51
	
51
	
52
	public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
52
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
53
	super(METHOD_SCOPE, parent);
54
	locals = new LocalVariableBinding[5];
55
	this.referenceContext = context;
56
	this.isStatic = isStatic;
57
	this.startIndex = 0;
58
}
53
59
54
		super(METHOD_SCOPE, parent);
60
String basicToString(int tab) {
55
		locals = new LocalVariableBinding[5];
61
	String newLine = "\n"; //$NON-NLS-1$
56
		this.referenceContext = context;
62
	for (int i = tab; --i >= 0;)
57
		this.isStatic = isStatic;
63
		newLine += "\t"; //$NON-NLS-1$
58
		this.startIndex = 0;
64
59
	}
65
	String s = newLine + "--- Method Scope ---"; //$NON-NLS-1$
60
66
	newLine += "\t"; //$NON-NLS-1$
61
	/* Spec : 8.4.3 & 9.4
67
	s += newLine + "locals:"; //$NON-NLS-1$
62
	 */
68
	for (int i = 0; i < localIndex; i++)
63
	private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) {
69
		s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$
64
		
70
	s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$
65
		int modifiers = methodBinding.modifiers;
71
	s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$
66
		final ReferenceBinding declaringClass = methodBinding.declaringClass;
72
	s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$
67
		if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
73
	s += newLine + "lastVisibleFieldID = " + lastVisibleFieldID; //$NON-NLS-1$
68
			problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
74
	s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$
69
75
	return s;
70
		if ((((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) != 0) {
76
}
71
			// certain flags are propagated from declaring class onto constructor
77
72
			final int DECLARING_FLAGS = ClassFileConstants.AccEnum|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected;
78
/**
73
			final int VISIBILITY_FLAGS = ClassFileConstants.AccPrivate|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected;
79
 * Spec : 8.4.3 & 9.4
74
			int flags;
80
 */
75
			if ((flags = declaringClass.modifiers & DECLARING_FLAGS) != 0) {
81
private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) {
76
				if ((flags & ClassFileConstants.AccEnum) != 0) {
82
	int modifiers = methodBinding.modifiers;
77
					modifiers &= ~VISIBILITY_FLAGS;
83
	final ReferenceBinding declaringClass = methodBinding.declaringClass;
78
					modifiers |= ClassFileConstants.AccPrivate; // default constructor is implicitly private in enum
84
	if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
79
				} else {
85
		problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
80
					modifiers &= ~VISIBILITY_FLAGS;
86
81
					modifiers |= flags; // propagate public/protected
87
	if ((((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) != 0) {
82
				}
88
		// certain flags are propagated from declaring class onto constructor
89
		final int DECLARING_FLAGS = ClassFileConstants.AccEnum|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected;
90
		final int VISIBILITY_FLAGS = ClassFileConstants.AccPrivate|ClassFileConstants.AccPublic|ClassFileConstants.AccProtected;
91
		int flags;
92
		if ((flags = declaringClass.modifiers & DECLARING_FLAGS) != 0) {
93
			if ((flags & ClassFileConstants.AccEnum) != 0) {
94
				modifiers &= ~VISIBILITY_FLAGS;
95
				modifiers |= ClassFileConstants.AccPrivate; // default constructor is implicitly private in enum
96
			} else {
97
				modifiers &= ~VISIBILITY_FLAGS;
98
				modifiers |= flags; // propagate public/protected
83
			}
99
			}
84
		}
100
		}
101
	}
85
102
86
		// after this point, tests on the 16 bits reserved.
103
	// after this point, tests on the 16 bits reserved.
87
		int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
104
	int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
88
105
89
		// check for abnormal modifiers
106
	// check for abnormal modifiers
90
		final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStrictfp);
107
	final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected | ClassFileConstants.AccStrictfp);
91
		if (declaringClass.isEnum() && (((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) == 0) {
108
	if (declaringClass.isEnum() && (((ConstructorDeclaration) referenceContext).bits & ASTNode.IsDefaultConstructor) == 0) {
92
			final int UNEXPECTED_ENUM_CONSTR_MODIFIERS = ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStrictfp);
109
		final int UNEXPECTED_ENUM_CONSTR_MODIFIERS = ~(ClassFileConstants.AccPrivate | ClassFileConstants.AccStrictfp);
93
			if ((realModifiers & UNEXPECTED_ENUM_CONSTR_MODIFIERS) != 0) {
110
		if ((realModifiers & UNEXPECTED_ENUM_CONSTR_MODIFIERS) != 0) {
94
				problemReporter().illegalModifierForEnumConstructor((AbstractMethodDeclaration) referenceContext);
111
			problemReporter().illegalModifierForEnumConstructor((AbstractMethodDeclaration) referenceContext);
95
				modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_ENUM_CONSTR_MODIFIERS;
112
			modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_ENUM_CONSTR_MODIFIERS;
96
			} else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) {
97
				// must check the parse node explicitly
98
				problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
99
			}
100
			modifiers |= ClassFileConstants.AccPrivate; // enum constructor is implicitly private
101
		} else if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
102
			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
103
			modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS;
104
		} else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) {
113
		} else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) {
105
			// must check the parse node explicitly
114
			// must check the parse node explicitly
106
			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
115
			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
107
		}
116
		}
108
117
		modifiers |= ClassFileConstants.AccPrivate; // enum constructor is implicitly private
109
		// check for incompatible modifiers in the visibility bits, isolate the visibility bits
118
	} else if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
110
		int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
119
		problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
111
		if ((accessorBits & (accessorBits - 1)) != 0) {
120
		modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS;
112
			problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
121
	} else if ((((AbstractMethodDeclaration) referenceContext).modifiers & ClassFileConstants.AccStrictfp) != 0) {
113
122
		// must check the parse node explicitly
114
			// need to keep the less restrictive so disable Protected/Private as necessary
123
		problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
115
			if ((accessorBits & ClassFileConstants.AccPublic) != 0) {
124
	}
116
				if ((accessorBits & ClassFileConstants.AccProtected) != 0)
125
117
					modifiers &= ~ClassFileConstants.AccProtected;
126
	// check for incompatible modifiers in the visibility bits, isolate the visibility bits
118
				if ((accessorBits & ClassFileConstants.AccPrivate) != 0)
127
	int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
119
					modifiers &= ~ClassFileConstants.AccPrivate;
128
	if ((accessorBits & (accessorBits - 1)) != 0) {
120
			} else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) {
129
		problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
130
131
		// need to keep the less restrictive so disable Protected/Private as necessary
132
		if ((accessorBits & ClassFileConstants.AccPublic) != 0) {
133
			if ((accessorBits & ClassFileConstants.AccProtected) != 0)
134
				modifiers &= ~ClassFileConstants.AccProtected;
135
			if ((accessorBits & ClassFileConstants.AccPrivate) != 0)
121
				modifiers &= ~ClassFileConstants.AccPrivate;
136
				modifiers &= ~ClassFileConstants.AccPrivate;
122
			}
137
		} else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) {
138
			modifiers &= ~ClassFileConstants.AccPrivate;
123
		}
139
		}
140
	}
124
141
125
//		// 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)
142
//		// 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)
126
//		if (declaringClass.isPrivate() && (modifiers & ClassFileConstants.AccPrivate) != 0)
143
//		if (declaringClass.isPrivate() && (modifiers & ClassFileConstants.AccPrivate) != 0)
127
//			modifiers &= ~ClassFileConstants.AccPrivate;
144
//			modifiers &= ~ClassFileConstants.AccPrivate;
128
145
129
		methodBinding.modifiers = modifiers;
146
	methodBinding.modifiers = modifiers;
130
	}
147
}
131
	
132
	/* Spec : 8.4.3 & 9.4
133
	 */
134
	private void checkAndSetModifiersForMethod(MethodBinding methodBinding) {
135
		
136
		int modifiers = methodBinding.modifiers;
137
		final ReferenceBinding declaringClass = methodBinding.declaringClass;
138
		if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
139
			problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
140
141
		// after this point, tests on the 16 bits reserved.
142
		int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
143
144
		// set the requested modifiers for a method in an interface/annotation
145
		if (declaringClass.isInterface()) {
146
			if ((realModifiers & ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract)) != 0) {
147
				if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0)
148
					problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) referenceContext);
149
				else
150
					problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) referenceContext);
151
			}
152
			return;
153
		}
154
155
		// check for abnormal modifiers
156
		final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected
157
			| ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp);
158
		if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
159
			problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
160
			modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS;
161
		}
162
148
163
		// check for incompatible modifiers in the visibility bits, isolate the visibility bits
149
/**
164
		int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
150
 * Spec : 8.4.3 & 9.4
165
		if ((accessorBits & (accessorBits - 1)) != 0) {
151
 */
166
			problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
152
private void checkAndSetModifiersForMethod(MethodBinding methodBinding) {
167
153
	int modifiers = methodBinding.modifiers;
168
			// need to keep the less restrictive so disable Protected/Private as necessary
154
	final ReferenceBinding declaringClass = methodBinding.declaringClass;
169
			if ((accessorBits & ClassFileConstants.AccPublic) != 0) {
155
	if ((modifiers & ExtraCompilerModifiers.AccAlternateModifierProblem) != 0)
170
				if ((accessorBits & ClassFileConstants.AccProtected) != 0)
156
		problemReporter().duplicateModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
171
					modifiers &= ~ClassFileConstants.AccProtected;
157
172
				if ((accessorBits & ClassFileConstants.AccPrivate) != 0)
158
	// after this point, tests on the 16 bits reserved.
173
					modifiers &= ~ClassFileConstants.AccPrivate;
159
	int realModifiers = modifiers & ExtraCompilerModifiers.AccJustFlag;
174
			} else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) {
160
161
	// set the requested modifiers for a method in an interface/annotation
162
	if (declaringClass.isInterface()) {
163
		if ((realModifiers & ~(ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract)) != 0) {
164
			if ((declaringClass.modifiers & ClassFileConstants.AccAnnotation) != 0)
165
				problemReporter().illegalModifierForAnnotationMember((AbstractMethodDeclaration) referenceContext);
166
			else
167
				problemReporter().illegalModifierForInterfaceMethod((AbstractMethodDeclaration) referenceContext);
168
		}
169
		return;
170
	}
171
172
	// check for abnormal modifiers
173
	final int UNEXPECTED_MODIFIERS = ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected
174
		| ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp);
175
	if ((realModifiers & UNEXPECTED_MODIFIERS) != 0) {
176
		problemReporter().illegalModifierForMethod((AbstractMethodDeclaration) referenceContext);
177
		modifiers &= ~ExtraCompilerModifiers.AccJustFlag | ~UNEXPECTED_MODIFIERS;
178
	}
179
180
	// check for incompatible modifiers in the visibility bits, isolate the visibility bits
181
	int accessorBits = realModifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccProtected | ClassFileConstants.AccPrivate);
182
	if ((accessorBits & (accessorBits - 1)) != 0) {
183
		problemReporter().illegalVisibilityModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
184
185
		// need to keep the less restrictive so disable Protected/Private as necessary
186
		if ((accessorBits & ClassFileConstants.AccPublic) != 0) {
187
			if ((accessorBits & ClassFileConstants.AccProtected) != 0)
188
				modifiers &= ~ClassFileConstants.AccProtected;
189
			if ((accessorBits & ClassFileConstants.AccPrivate) != 0)
175
				modifiers &= ~ClassFileConstants.AccPrivate;
190
				modifiers &= ~ClassFileConstants.AccPrivate;
176
			}
191
		} else if ((accessorBits & ClassFileConstants.AccProtected) != 0 && (accessorBits & ClassFileConstants.AccPrivate) != 0) {
192
			modifiers &= ~ClassFileConstants.AccPrivate;
177
		}
193
		}
194
	}
178
195
179
		// check for modifiers incompatible with abstract modifier
196
	// check for modifiers incompatible with abstract modifier
180
		if ((modifiers & ClassFileConstants.AccAbstract) != 0) {
197
	if ((modifiers & ClassFileConstants.AccAbstract) != 0) {
181
			int incompatibleWithAbstract = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp;
198
		int incompatibleWithAbstract = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative | ClassFileConstants.AccStrictfp;
182
			if ((modifiers & incompatibleWithAbstract) != 0)
199
		if ((modifiers & incompatibleWithAbstract) != 0)
183
				problemReporter().illegalAbstractModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
200
			problemReporter().illegalAbstractModifierCombinationForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
184
			if (!methodBinding.declaringClass.isAbstract())
201
		if (!methodBinding.declaringClass.isAbstract())
185
				problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) declaringClass, (AbstractMethodDeclaration) referenceContext);
202
			problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) declaringClass, (AbstractMethodDeclaration) referenceContext);
186
		}
187
188
		/* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final)
189
		// methods from a final class are final : 8.4.3.3 
190
		if (methodBinding.declaringClass.isFinal())
191
			modifiers |= AccFinal;
192
		*/
193
		// native methods cannot also be tagged as strictfp
194
		if ((modifiers & ClassFileConstants.AccNative) != 0 && (modifiers & ClassFileConstants.AccStrictfp) != 0)
195
			problemReporter().nativeMethodsCannotBeStrictfp(declaringClass, (AbstractMethodDeclaration) referenceContext);
196
197
		// static members are only authorized in a static member or top level type
198
		if (((realModifiers & ClassFileConstants.AccStatic) != 0) && declaringClass.isNestedType() && !declaringClass.isStatic())
199
			problemReporter().unexpectedStaticModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
200
201
		methodBinding.modifiers = modifiers;
202
	}
203
	}
203
	
204
204
	/* Compute variable positions in scopes given an initial position offset
205
	/* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final)
205
	 * ignoring unused local variables.
206
	// methods from a final class are final : 8.4.3.3 
206
	 * 
207
	if (methodBinding.declaringClass.isFinal())
207
	 * Deal with arguments here, locals and subscopes are processed in BlockScope method
208
		modifiers |= AccFinal;
208
	 */
209
	*/
209
	public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) {
210
	// native methods cannot also be tagged as strictfp
210
211
	if ((modifiers & ClassFileConstants.AccNative) != 0 && (modifiers & ClassFileConstants.AccStrictfp) != 0)
211
		boolean isReportingUnusedArgument = false;
212
		problemReporter().nativeMethodsCannotBeStrictfp(declaringClass, (AbstractMethodDeclaration) referenceContext);
212
213
213
		if (referenceContext instanceof AbstractMethodDeclaration) {
214
	// static members are only authorized in a static member or top level type
214
			AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)referenceContext;
215
	if (((realModifiers & ClassFileConstants.AccStatic) != 0) && declaringClass.isNestedType() && !declaringClass.isStatic())
215
			MethodBinding method = methodDecl.binding;
216
		problemReporter().unexpectedStaticModifierForMethod(declaringClass, (AbstractMethodDeclaration) referenceContext);
216
			if (!(method.isAbstract()
217
217
					|| (method.isImplementing() && !compilerOptions().reportUnusedParameterWhenImplementingAbstract) 
218
	methodBinding.modifiers = modifiers;
218
					|| (method.isOverriding() && !method.isImplementing() && !compilerOptions().reportUnusedParameterWhenOverridingConcrete)
219
}
219
					|| method.isMain())) {
220
220
				isReportingUnusedArgument = true;
221
/**
221
			}
222
 * Compute variable positions in scopes given an initial position offset
223
 * ignoring unused local variables.
224
 * 
225
 * Deal with arguments here, locals and subscopes are processed in BlockScope method
226
 */
227
public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) {
228
229
	boolean isReportingUnusedArgument = false;
230
231
	if (referenceContext instanceof AbstractMethodDeclaration) {
232
		AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)referenceContext;
233
		MethodBinding method = methodDecl.binding;
234
		if (!(method.isAbstract()
235
				|| (method.isImplementing() && !compilerOptions().reportUnusedParameterWhenImplementingAbstract) 
236
				|| (method.isOverriding() && !method.isImplementing() && !compilerOptions().reportUnusedParameterWhenOverridingConcrete)
237
				|| method.isMain())) {
238
			isReportingUnusedArgument = true;
222
		}
239
		}
223
		this.offset = initOffset;
240
	}
224
		this.maxOffset = initOffset;
241
	this.offset = initOffset;
242
	this.maxOffset = initOffset;
225
243
226
		// manage arguments	
244
	// manage arguments	
227
		int ilocal = 0, maxLocals = this.localIndex;
245
	int ilocal = 0, maxLocals = this.localIndex;
228
		while (ilocal < maxLocals) {
246
	while (ilocal < maxLocals) {
229
			LocalVariableBinding local = locals[ilocal];
247
		LocalVariableBinding local = locals[ilocal];
230
			if (local == null || ((local.tagBits & TagBits.IsArgument) == 0)) break; // done with arguments
248
		if (local == null || ((local.tagBits & TagBits.IsArgument) == 0)) break; // done with arguments
231
249
232
			// do not report fake used variable
250
		// do not report fake used variable
233
			if (isReportingUnusedArgument
251
		if (isReportingUnusedArgument
234
					&& local.useFlag == LocalVariableBinding.UNUSED
252
				&& local.useFlag == LocalVariableBinding.UNUSED
235
					&& ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable
253
				&& ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable
236
				this.problemReporter().unusedArgument(local.declaration);
254
			this.problemReporter().unusedArgument(local.declaration);
237
			}
255
		}
238
256
239
			// record user-defined argument for attribute generation
257
		// record user-defined argument for attribute generation
240
			codeStream.record(local); 
258
		codeStream.record(local); 
241
259
242
			// assign variable position
260
		// assign variable position
243
			local.resolvedPosition = this.offset;
261
		local.resolvedPosition = this.offset;
244
262
245
			if ((local.type == TypeBinding.LONG) || (local.type == TypeBinding.DOUBLE)) {
263
		if ((local.type == TypeBinding.LONG) || (local.type == TypeBinding.DOUBLE)) {
264
			this.offset += 2;
265
		} else {
266
			this.offset++;
267
		}
268
		// check for too many arguments/local variables
269
		if (this.offset > 0xFF) { // no more than 255 words of arguments
270
			this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration);
271
		}
272
		ilocal++;
273
	}
274
	
275
	// sneak in extra argument before other local variables
276
	if (extraSyntheticArguments != null) {
277
		for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg < maxArguments; iarg++){
278
			SyntheticArgumentBinding argument = extraSyntheticArguments[iarg];
279
			argument.resolvedPosition = this.offset;
280
			if ((argument.type == TypeBinding.LONG) || (argument.type == TypeBinding.DOUBLE)){
246
				this.offset += 2;
281
				this.offset += 2;
247
			} else {
282
			} else {
248
				this.offset++;
283
				this.offset++;
249
			}
284
			}
250
			// check for too many arguments/local variables
251
			if (this.offset > 0xFF) { // no more than 255 words of arguments
285
			if (this.offset > 0xFF) { // no more than 255 words of arguments
252
				this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration);
286
				this.problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); 
253
			}
287
			}
254
			ilocal++;
255
		}
288
		}
256
		
257
		// sneak in extra argument before other local variables
258
		if (extraSyntheticArguments != null) {
259
			for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg < maxArguments; iarg++){
260
				SyntheticArgumentBinding argument = extraSyntheticArguments[iarg];
261
				argument.resolvedPosition = this.offset;
262
				if ((argument.type == TypeBinding.LONG) || (argument.type == TypeBinding.DOUBLE)){
263
					this.offset += 2;
264
				} else {
265
					this.offset++;
266
				}
267
				if (this.offset > 0xFF) { // no more than 255 words of arguments
268
					this.problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); 
269
				}
270
			}
271
		}
272
		this.computeLocalVariablePositions(ilocal, this.offset, codeStream);
273
	}
289
	}
290
	this.computeLocalVariablePositions(ilocal, this.offset, codeStream);
291
}
274
292
275
	/* Error management:
293
/**
276
	 * 		keep null for all the errors that prevent the method to be created
294
 * Error management:
277
	 * 		otherwise return a correct method binding (but without the element
295
 * 		keep null for all the errors that prevent the method to be created
278
	 *		that caused the problem) : ie : Incorrect thrown exception
296
 * 		otherwise return a correct method binding (but without the element
279
	 */
297
 *		that caused the problem) : ie : Incorrect thrown exception
280
	MethodBinding createMethod(AbstractMethodDeclaration method) {
298
 */
281
299
MethodBinding createMethod(AbstractMethodDeclaration method) {
282
		// is necessary to ensure error reporting
300
	// is necessary to ensure error reporting
283
		this.referenceContext = method;
301
	this.referenceContext = method;
284
		method.scope = this;
302
	method.scope = this;
285
		SourceTypeBinding declaringClass = referenceType().binding;
303
	SourceTypeBinding declaringClass = referenceType().binding;
286
		int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved;
304
	int modifiers = method.modifiers | ExtraCompilerModifiers.AccUnresolved;
287
		if (method.isConstructor()) {
305
	if (method.isConstructor()) {
288
			if (method.isDefaultConstructor())
306
		if (method.isDefaultConstructor())
289
				modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor;
307
			modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor;
290
			method.binding = new MethodBinding(modifiers, null, null, declaringClass);
308
		method.binding = new MethodBinding(modifiers, null, null, declaringClass);
291
			checkAndSetModifiersForConstructor(method.binding);
309
		checkAndSetModifiersForConstructor(method.binding);
292
		} else {
310
	} else {
293
			if (declaringClass.isInterface()) // interface or annotation type
311
		if (declaringClass.isInterface()) // interface or annotation type
294
				modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;
312
			modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract;
295
			method.binding =
313
		method.binding =
296
				new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
314
			new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
297
			checkAndSetModifiersForMethod(method.binding);
315
		checkAndSetModifiersForMethod(method.binding);
298
		}
316
	}
299
		this.isStatic = method.binding.isStatic();
317
	this.isStatic = method.binding.isStatic();
300
318
301
		Argument[] argTypes = method.arguments;
319
	Argument[] argTypes = method.arguments;
302
		int argLength = argTypes == null ? 0 : argTypes.length;
320
	int argLength = argTypes == null ? 0 : argTypes.length;
303
		if (argLength > 0 && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
321
	if (argLength > 0 && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
304
			if (argTypes[--argLength].isVarArgs())
322
		if (argTypes[--argLength].isVarArgs())
305
				method.binding.modifiers |= ClassFileConstants.AccVarargs;
323
			method.binding.modifiers |= ClassFileConstants.AccVarargs;
306
			while (--argLength >= 0) {
324
		while (--argLength >= 0) {
307
				if (argTypes[argLength].isVarArgs())
325
			if (argTypes[argLength].isVarArgs())
308
					problemReporter().illegalVararg(argTypes[argLength], method);
326
				problemReporter().illegalVararg(argTypes[argLength], method);
309
			}
310
		}
311
		
312
		TypeParameter[] typeParameters = method.typeParameters();
313
	    // do not construct type variables if source < 1.5
314
		if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
315
		    method.binding.typeVariables = Binding.NO_TYPE_VARIABLES;
316
		} else {
317
			method.binding.typeVariables = createTypeVariables(typeParameters, method.binding);
318
			method.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
319
		}
327
		}
320
		return method.binding;
321
	}
328
	}
322
323
	/* Overridden to detect the error case inside an explicit constructor call:
324
	
329
	
325
	class X {
330
	TypeParameter[] typeParameters = method.typeParameters();
326
		int i;
331
    // do not construct type variables if source < 1.5
327
		X myX;
332
	if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
328
		X(X x) {
333
	    method.binding.typeVariables = Binding.NO_TYPE_VARIABLES;
329
			this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors
334
	} else {
330
		}
335
		method.binding.typeVariables = createTypeVariables(typeParameters, method.binding);
336
		method.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
331
	}
337
	}
332
	*/
338
	return method.binding;
333
	public FieldBinding findField(
339
}
334
		TypeBinding receiverType,
335
		char[] fieldName,
336
		InvocationSite invocationSite,
337
		boolean needResolve) {
338
339
		FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve);
340
		if (field == null)
341
			return null;
342
		if (!field.isValidBinding())
343
			return field; // answer the error field
344
		if (field.isStatic())
345
			return field; // static fields are always accessible
346
340
347
		if (!isConstructorCall || receiverType != enclosingSourceType())
341
/**
348
			return field;
342
 * Overridden to detect the error case inside an explicit constructor call:
343
class X {
344
	int i;
345
	X myX;
346
	X(X x) {
347
		this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors
348
	}
349
}
350
 */
351
public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
352
353
	FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve);
354
	if (field == null)
355
		return null;
356
	if (!field.isValidBinding())
357
		return field; // answer the error field
358
	if (field.isStatic())
359
		return field; // static fields are always accessible
360
361
	if (!isConstructorCall || receiverType != enclosingSourceType())
362
		return field;
349
363
350
		if (invocationSite instanceof SingleNameReference)
364
	if (invocationSite instanceof SingleNameReference)
365
		return new ProblemFieldBinding(
366
			field, // closest match
367
			field.declaringClass,
368
			fieldName,
369
			ProblemReasons.NonStaticReferenceInConstructorInvocation);
370
	if (invocationSite instanceof QualifiedNameReference) {
371
		// look to see if the field is the first binding
372
		QualifiedNameReference name = (QualifiedNameReference) invocationSite;
373
		if (name.binding == null)
374
			// only true when the field is the fieldbinding at the beginning of name's tokens
351
			return new ProblemFieldBinding(
375
			return new ProblemFieldBinding(
352
				field, // closest match
376
				field, // closest match
353
				field.declaringClass,
377
				field.declaringClass,
354
				fieldName,
378
				fieldName,
355
				ProblemReasons.NonStaticReferenceInConstructorInvocation);
379
				ProblemReasons.NonStaticReferenceInConstructorInvocation);
356
		if (invocationSite instanceof QualifiedNameReference) {
357
			// look to see if the field is the first binding
358
			QualifiedNameReference name = (QualifiedNameReference) invocationSite;
359
			if (name.binding == null)
360
				// only true when the field is the fieldbinding at the beginning of name's tokens
361
				return new ProblemFieldBinding(
362
					field, // closest match
363
					field.declaringClass,
364
					fieldName,
365
					ProblemReasons.NonStaticReferenceInConstructorInvocation);
366
		}
367
		return field;
368
	}
369
370
	public boolean isInsideConstructor() {
371
372
		return (referenceContext instanceof ConstructorDeclaration);
373
	}
374
	
375
	public boolean isInsideInitializer() {
376
377
		return (referenceContext instanceof TypeDeclaration);
378
	}
380
	}
381
	return field;
382
}
379
383
380
	public boolean isInsideInitializerOrConstructor() {
384
public boolean isInsideConstructor() {
385
	return (referenceContext instanceof ConstructorDeclaration);
386
}
381
387
382
		return (referenceContext instanceof TypeDeclaration)
388
public boolean isInsideInitializer() {
383
			|| (referenceContext instanceof ConstructorDeclaration);
389
	return (referenceContext instanceof TypeDeclaration);
384
	}
390
}
385
391
386
	/* Answer the problem reporter to use for raising new problems.
392
public boolean isInsideInitializerOrConstructor() {
387
	 *
393
	return (referenceContext instanceof TypeDeclaration)
388
	 * Note that as a side-effect, this updates the current reference context
394
		|| (referenceContext instanceof ConstructorDeclaration);
389
	 * (unit, type or method) in case the problem handler decides it is necessary
395
}
390
	 * to abort.
391
	 */
392
	public ProblemReporter problemReporter() {
393
396
394
		MethodScope outerMethodScope;
397
/**
395
		if ((outerMethodScope = outerMostMethodScope()) == this) {
398
 * Answer the problem reporter to use for raising new problems.
396
			ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
399
 *
397
			problemReporter.referenceContext = referenceContext;
400
 * Note that as a side-effect, this updates the current reference context
398
			return problemReporter;
401
 * (unit, type or method) in case the problem handler decides it is necessary
399
		}
402
 * to abort.
400
		return outerMethodScope.problemReporter();
403
 */
404
public ProblemReporter problemReporter() {
405
	MethodScope outerMethodScope;
406
	if ((outerMethodScope = outerMostMethodScope()) == this) {
407
		ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
408
		problemReporter.referenceContext = referenceContext;
409
		return problemReporter;
401
	}
410
	}
411
	return outerMethodScope.problemReporter();
412
}
402
413
403
	public final int recordInitializationStates(FlowInfo flowInfo) {
414
public final int recordInitializationStates(FlowInfo flowInfo) {
404
415
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return -1;
405
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return -1;
416
	UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInitsWithoutSideEffect();
406
417
	long[] extraInits = unconditionalFlowInfo.extra == null ?
407
		UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInitsWithoutSideEffect();
418
			null : unconditionalFlowInfo.extra[0];
408
		long[] extraInits = unconditionalFlowInfo.extra == null ?
419
	long inits = unconditionalFlowInfo.definiteInits;
409
				null : unconditionalFlowInfo.extra[0];
420
	checkNextEntry : for (int i = lastIndex; --i >= 0;) {
410
		long inits = unconditionalFlowInfo.definiteInits;
421
		if (definiteInits[i] == inits) {
411
		checkNextEntry : for (int i = lastIndex; --i >= 0;) {
422
			long[] otherInits = extraDefiniteInits[i];
412
			if (definiteInits[i] == inits) {
423
			if ((extraInits != null) && (otherInits != null)) {
413
				long[] otherInits = extraDefiniteInits[i];
424
				if (extraInits.length == otherInits.length) {
414
				if ((extraInits != null) && (otherInits != null)) {
425
					int j, max;
415
					if (extraInits.length == otherInits.length) {
426
					for (j = 0, max = extraInits.length; j < max; j++) {
416
						int j, max;
427
						if (extraInits[j] != otherInits[j]) {
417
						for (j = 0, max = extraInits.length; j < max; j++) {
428
							continue checkNextEntry;
418
							if (extraInits[j] != otherInits[j]) {
419
								continue checkNextEntry;
420
							}
421
						}
429
						}
422
						return i;
423
					}
424
				} else {
425
					if ((extraInits == null) && (otherInits == null)) {
426
						return i;
427
					}
430
					}
431
					return i;
432
				}
433
			} else {
434
				if ((extraInits == null) && (otherInits == null)) {
435
					return i;
428
				}
436
				}
429
			}
437
			}
430
		}
438
		}
431
432
		// add a new entry
433
		if (definiteInits.length == lastIndex) {
434
			// need a resize
435
			System.arraycopy(
436
				definiteInits,
437
				0,
438
				(definiteInits = new long[lastIndex + 20]),
439
				0,
440
				lastIndex);
441
			System.arraycopy(
442
				extraDefiniteInits,
443
				0,
444
				(extraDefiniteInits = new long[lastIndex + 20][]),
445
				0,
446
				lastIndex);
447
		}
448
		definiteInits[lastIndex] = inits;
449
		if (extraInits != null) {
450
			extraDefiniteInits[lastIndex] = new long[extraInits.length];
451
			System.arraycopy(
452
				extraInits,
453
				0,
454
				extraDefiniteInits[lastIndex],
455
				0,
456
				extraInits.length);
457
		}
458
		return lastIndex++;
459
	}
460
461
	/* Answer the reference method of this scope, or null if initialization scoope.
462
	*/
463
	public AbstractMethodDeclaration referenceMethod() {
464
465
		if (referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) referenceContext;
466
		return null;
467
	}
439
	}
468
440
469
	/* Answer the reference type of this scope.
441
	// add a new entry
470
	*
442
	if (definiteInits.length == lastIndex) {
471
	* It is the nearest enclosing type of this scope.
443
		// need a resize
472
	*/
444
		System.arraycopy(
473
	public TypeDeclaration referenceType() {
445
			definiteInits,
474
446
			0,
475
		return ((ClassScope) parent).referenceContext;
447
			(definiteInits = new long[lastIndex + 20]),
448
			0,
449
			lastIndex);
450
		System.arraycopy(
451
			extraDefiniteInits,
452
			0,
453
			(extraDefiniteInits = new long[lastIndex + 20][]),
454
			0,
455
			lastIndex);
456
	}
457
	definiteInits[lastIndex] = inits;
458
	if (extraInits != null) {
459
		extraDefiniteInits[lastIndex] = new long[extraInits.length];
460
		System.arraycopy(
461
			extraInits,
462
			0,
463
			extraDefiniteInits[lastIndex],
464
			0,
465
			extraInits.length);
476
	}
466
	}
467
	return lastIndex++;
468
}
477
469
478
	String basicToString(int tab) {
470
/**
479
471
 *  Answer the reference method of this scope, or null if initialization scoope.
480
		String newLine = "\n"; //$NON-NLS-1$
472
 */
481
		for (int i = tab; --i >= 0;)
473
public AbstractMethodDeclaration referenceMethod() {
482
			newLine += "\t"; //$NON-NLS-1$
474
	if (referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) referenceContext;
483
475
	return null;
484
		String s = newLine + "--- Method Scope ---"; //$NON-NLS-1$
476
}
485
		newLine += "\t"; //$NON-NLS-1$
486
		s += newLine + "locals:"; //$NON-NLS-1$
487
		for (int i = 0; i < localIndex; i++)
488
			s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$
489
		s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$
490
		s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$
491
		s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$
492
		s += newLine + "lastVisibleFieldID = " + lastVisibleFieldID; //$NON-NLS-1$
493
		s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$
494
		return s;
495
	}
496
477
478
/**
479
 *  Answer the reference type of this scope.
480
 * It is the nearest enclosing type of this scope.
481
 */
482
public TypeDeclaration referenceType() {
483
	return ((ClassScope) parent).referenceContext;
484
}
497
}
485
}
(-)compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java (-2 / +27 lines)
Lines 111-118 Link Here
111
	this.subscopes[this.subscopeCount++] = childScope;
111
	this.subscopes[this.subscopeCount++] = childScope;
112
}
112
}
113
113
114
/* Answer true if the receiver is suitable for assigning final blank fields.
114
/**
115
 *
115
 * Answer true if the receiver is suitable for assigning final blank fields.
116
 * in other words, it is inside an initializer, a constructor or a clinit 
116
 * in other words, it is inside an initializer, a constructor or a clinit 
117
 */
117
 */
118
public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) {
118
public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) {
Lines 125-130 Link Here
125
	return methodScope.isInsideInitializer() // inside initializer
125
	return methodScope.isInsideInitializer() // inside initializer
126
			|| ((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod(); // inside constructor or clinit
126
			|| ((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod(); // inside constructor or clinit
127
}
127
}
128
128
String basicToString(int tab) {
129
String basicToString(int tab) {
129
	String newLine = "\n"; //$NON-NLS-1$
130
	String newLine = "\n"; //$NON-NLS-1$
130
	for (int i = tab; --i >= 0;)
131
	for (int i = tab; --i >= 0;)
Lines 822-827 Link Here
822
	return max;
823
	return max;
823
}
824
}
824
825
826
/**
827
 * Returns true if the context requires to check initialization of final blank fields.
828
 * in other words, it is inside an initializer, a constructor or a clinit 
829
 */
830
public final boolean needBlankFinalFieldInitializationCheck(FieldBinding binding) {
831
	boolean isStatic = binding.isStatic();
832
	ReferenceBinding fieldDeclaringClass = binding.declaringClass;
833
	// loop in enclosing context, until reaching the field declaring context
834
	MethodScope methodScope = methodScope();
835
	while (methodScope != null) {
836
		if (methodScope.isStatic != isStatic)
837
			return false;
838
		if (!methodScope.isInsideInitializer() // inside initializer
839
				&& !((AbstractMethodDeclaration) methodScope.referenceContext).isInitializationMethod()) { // inside constructor or clinit
840
			return false; // found some non-initializer context
841
		}
842
		if (fieldDeclaringClass == methodScope.enclosingReceiverType()) {
843
			return true; // found the field context, no need to check any further
844
		}
845
		methodScope = methodScope.enclosingMethodScope();
846
	}
847
	return false;
848
}
849
825
/* Answer the problem reporter to use for raising new problems.
850
/* Answer the problem reporter to use for raising new problems.
826
 *
851
 *
827
 * Note that as a side-effect, this updates the current reference context
852
 * Note that as a side-effect, this updates the current reference context
(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java (-1 / +1 lines)
Lines 56-62 Link Here
56
			// check if reading a final blank field
56
			// check if reading a final blank field
57
			FieldBinding fieldBinding;
57
			FieldBinding fieldBinding;
58
			if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() 
58
			if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() 
59
					&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
59
					&& currentScope.needBlankFinalFieldInitializationCheck(fieldBinding)) {
60
				if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
60
				if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
61
					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
61
					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
62
				}
62
				}
(-)Eclipse Java Tests Compiler/org/eclipse/jdt/tests/compiler/regression/InitializationTest.java (+148 lines)
Lines 5473-5478 Link Here
5473
		assertTrue(false);
5473
		assertTrue(false);
5474
	}			
5474
	}			
5475
}
5475
}
5476
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061
5477
public void test192() {
5478
	this.runNegativeTest(
5479
		new String[] {
5480
			"X.java",
5481
			"public final class X {\n" + 
5482
			"	private final Object mObj;\n" + 
5483
			"	private final Object mDependent = new Object() {\n" + 
5484
			"		{\n" + 
5485
			"			Object o1 = mObj;\n" + 
5486
			"		}\n" + 
5487
			"		Object o2 = mObj;\n" + 
5488
			"		void foo() {\n" + 
5489
			"			Object o3 = mObj;\n" + 
5490
			"		}\n" + 
5491
			"	};\n" + 
5492
			"	public X() {\n" + 
5493
			"		mObj = \"\";\n" + 
5494
			"	}\n" + 
5495
			"}\n"
5496
		}, 
5497
		"----------\n" + 
5498
		"1. WARNING in X.java (at line 3)\n" + 
5499
		"	private final Object mDependent = new Object() {\n" + 
5500
		"	                     ^^^^^^^^^^\n" + 
5501
		"The field X.mDependent is never read locally\n" + 
5502
		"----------\n" + 
5503
		"2. WARNING in X.java (at line 5)\n" + 
5504
		"	Object o1 = mObj;\n" + 
5505
		"	            ^^^^\n" + 
5506
		"Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5507
		"----------\n" + 
5508
		"3. ERROR in X.java (at line 5)\n" + 
5509
		"	Object o1 = mObj;\n" + 
5510
		"	            ^^^^\n" + 
5511
		"The blank final field mObj may not have been initialized\n" + 
5512
		"----------\n" + 
5513
		"4. WARNING in X.java (at line 7)\n" + 
5514
		"	Object o2 = mObj;\n" + 
5515
		"	       ^^\n" + 
5516
		"The field new Object(){}.o2 is never read locally\n" + 
5517
		"----------\n" + 
5518
		"5. WARNING in X.java (at line 7)\n" + 
5519
		"	Object o2 = mObj;\n" + 
5520
		"	            ^^^^\n" + 
5521
		"Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5522
		"----------\n" + 
5523
		"6. ERROR in X.java (at line 7)\n" + 
5524
		"	Object o2 = mObj;\n" + 
5525
		"	            ^^^^\n" + 
5526
		"The blank final field mObj may not have been initialized\n" + 
5527
		"----------\n" + 
5528
		"7. WARNING in X.java (at line 8)\n" + 
5529
		"	void foo() {\n" + 
5530
		"	     ^^^^^\n" + 
5531
		"The method foo() from the type new Object(){} is never used locally\n" + 
5532
		"----------\n" + 
5533
		"8. WARNING in X.java (at line 9)\n" + 
5534
		"	Object o3 = mObj;\n" + 
5535
		"	            ^^^^\n" + 
5536
		"Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5537
		"----------\n");
5538
}
5539
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=203061 - variation
5540
public void test193() {
5541
	this.runNegativeTest(
5542
		new String[] {
5543
			"X.java",
5544
			"public final class X {\n" + 
5545
			"	private final Object mObj;\n" + 
5546
			"	private final Object mDependent = new Object() {\n" + 
5547
			"		{\n" + 
5548
			"			Object o1 = mObj;\n" + 
5549
			"			mObj = \"1\";\n" + 
5550
			"		}\n" + 
5551
			"		Object o2 = mObj = \"2\";\n" + 
5552
			"		void foo() {\n" + 
5553
			"			Object o3 = mObj;\n" + 
5554
			"			mObj = \"3\";\n" + 
5555
			"		}\n" + 
5556
			"	};\n" + 
5557
			"	public X() {\n" + 
5558
			"		mObj = \"\";\n" + 
5559
			"	}\n" + 
5560
			"}\n"
5561
		}, 
5562
		"----------\n" + 
5563
		"1. WARNING in X.java (at line 3)\n" + 
5564
		"	private final Object mDependent = new Object() {\n" + 
5565
		"	                     ^^^^^^^^^^\n" + 
5566
		"The field X.mDependent is never read locally\n" + 
5567
		"----------\n" + 
5568
		"2. WARNING in X.java (at line 5)\n" + 
5569
		"	Object o1 = mObj;\n" + 
5570
		"	            ^^^^\n" + 
5571
		"Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5572
		"----------\n" + 
5573
		"3. ERROR in X.java (at line 5)\n" + 
5574
		"	Object o1 = mObj;\n" + 
5575
		"	            ^^^^\n" + 
5576
		"The blank final field mObj may not have been initialized\n" + 
5577
		"----------\n" + 
5578
		"4. WARNING in X.java (at line 6)\n" + 
5579
		"	mObj = \"1\";\n" + 
5580
		"	^^^^\n" + 
5581
		"Write access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5582
		"----------\n" + 
5583
		"5. ERROR in X.java (at line 6)\n" + 
5584
		"	mObj = \"1\";\n" + 
5585
		"	^^^^\n" + 
5586
		"The final field X.mObj cannot be assigned\n" + 
5587
		"----------\n" + 
5588
		"6. WARNING in X.java (at line 8)\n" + 
5589
		"	Object o2 = mObj = \"2\";\n" + 
5590
		"	       ^^\n" + 
5591
		"The field new Object(){}.o2 is never read locally\n" + 
5592
		"----------\n" + 
5593
		"7. WARNING in X.java (at line 8)\n" + 
5594
		"	Object o2 = mObj = \"2\";\n" + 
5595
		"	            ^^^^\n" + 
5596
		"Write access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5597
		"----------\n" + 
5598
		"8. ERROR in X.java (at line 8)\n" + 
5599
		"	Object o2 = mObj = \"2\";\n" + 
5600
		"	            ^^^^\n" + 
5601
		"The final field X.mObj cannot be assigned\n" + 
5602
		"----------\n" + 
5603
		"9. WARNING in X.java (at line 9)\n" + 
5604
		"	void foo() {\n" + 
5605
		"	     ^^^^^\n" + 
5606
		"The method foo() from the type new Object(){} is never used locally\n" + 
5607
		"----------\n" + 
5608
		"10. WARNING in X.java (at line 10)\n" + 
5609
		"	Object o3 = mObj;\n" + 
5610
		"	            ^^^^\n" + 
5611
		"Read access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5612
		"----------\n" + 
5613
		"11. WARNING in X.java (at line 11)\n" + 
5614
		"	mObj = \"3\";\n" + 
5615
		"	^^^^\n" + 
5616
		"Write access to enclosing field X.mObj is emulated by a synthetic accessor method. Increasing its visibility will improve your performance\n" + 
5617
		"----------\n" + 
5618
		"12. ERROR in X.java (at line 11)\n" + 
5619
		"	mObj = \"3\";\n" + 
5620
		"	^^^^\n" + 
5621
		"The final field X.mObj cannot be assigned\n" + 
5622
		"----------\n");
5623
}
5476
public static Class testClass() {
5624
public static Class testClass() {
5477
	return InitializationTest.class;
5625
	return InitializationTest.class;
5478
}
5626
}

Return to bug 203061