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

Collapse All | Expand All

(-)eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java (+22 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jdt.internal.eval;
11
package org.eclipse.jdt.internal.eval;
12
12
13
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
13
import org.eclipse.jdt.internal.compiler.ast.Assignment;
14
import org.eclipse.jdt.internal.compiler.ast.Assignment;
14
import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
15
import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
15
import org.eclipse.jdt.internal.compiler.ast.Expression;
16
import org.eclipse.jdt.internal.compiler.ast.Expression;
Lines 25-30 Link Here
25
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
28
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
32
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
Lines 47-52 Link Here
47
	super(sources, positions, sourceStart, sourceEnd);
49
	super(sources, positions, sourceStart, sourceEnd);
48
	this.evaluationContext = evaluationContext;
50
	this.evaluationContext = evaluationContext;
49
}
51
}
52
53
/**
54
 * Check and/or redirect the field access to the delegate receiver if any
55
 */
56
public TypeBinding checkFieldAccess(BlockScope scope) {
57
	FieldBinding fieldBinding = (FieldBinding) this.binding;
58
	MethodScope methodScope = scope.methodScope();
59
	// check for forward references
60
	if (this.indexOfFirstFieldBinding == 1
61
			&& methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
62
			&& methodScope.lastVisibleFieldID >= 0
63
			&& fieldBinding.id >= methodScope.lastVisibleFieldID
64
			&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
65
		scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
66
	}
67
	this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
68
	this.bits |= Binding.FIELD;
69
	return getOtherFieldBindings(scope);
70
}
71
50
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
72
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
51
	int pc = codeStream.position;
73
	int pc = codeStream.position;
52
	if ((this.bits & Binding.VARIABLE) == 0) { // nothing to do if type ref
74
	if ((this.bits & Binding.VARIABLE) == 0) { // nothing to do if type ref
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java (-61 / +40 lines)
Lines 209-233 Link Here
209
	return flowInfo;
209
	return flowInfo;
210
}
210
}
211
211
212
/**
213
 * Check and/or redirect the field access to the delegate receiver if any
214
 */
215
public TypeBinding checkFieldAccess(BlockScope scope) {
216
	FieldBinding fieldBinding = (FieldBinding) this.binding;
217
	MethodScope methodScope = scope.methodScope();
218
	// check for forward references
219
	if (this.indexOfFirstFieldBinding == 1
220
			&& methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
221
			&& methodScope.lastVisibleFieldID >= 0
222
			&& fieldBinding.id >= methodScope.lastVisibleFieldID
223
			&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
224
		scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
225
	}
226
	this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
227
	this.bits |= Binding.FIELD;
228
	return getOtherFieldBindings(scope);
229
}
230
231
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) {
212
public void checkNPE(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo, boolean checkString) {
232
	// cannot override localVariableBinding because this would project o.m onto o when
213
	// cannot override localVariableBinding because this would project o.m onto o when
233
	// analysing assignments
214
	// analysing assignments
Lines 682-708 Link Here
682
public TypeBinding getOtherFieldBindings(BlockScope scope) {
663
public TypeBinding getOtherFieldBindings(BlockScope scope) {
683
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
664
	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
684
	int length = this.tokens.length;
665
	int length = this.tokens.length;
685
	FieldBinding field;
666
	FieldBinding field = ((this.bits & Binding.FIELD) != 0) ? (FieldBinding) this.binding : null;
686
	if ((this.bits & Binding.FIELD) != 0) {
687
		field = (FieldBinding) this.binding;
688
		if (!field.isStatic()) {
689
			//must check for the static status....
690
			if (this.indexOfFirstFieldBinding > 1  //accessing to a field using a type as "receiver" is allowed only with static field
691
					 || scope.methodScope().isStatic) { 	// the field is the first token of the qualified reference....
692
				scope.problemReporter().staticFieldAccessToNonStaticVariable(this, field);
693
				return null;
694
			 }
695
		} else if (this.indexOfFirstFieldBinding > 1
696
					&& field.declaringClass != this.actualReceiverType
697
					&& field.declaringClass.canBeSeenBy(scope)) {
698
			scope.problemReporter().indirectAccessToStaticField(this, field);
699
		}
700
		// only last field is actually a write access if any
701
		if (isFieldUseDeprecated(field, scope, (this.bits & ASTNode.IsStrictlyAssigned) != 0 && this.indexOfFirstFieldBinding == length))
702
			scope.problemReporter().deprecatedField(field, this);
703
	} else {
704
		field = null;
705
	}
706
	TypeBinding type = ((VariableBinding) this.binding).type;
667
	TypeBinding type = ((VariableBinding) this.binding).type;
707
	int index = this.indexOfFirstFieldBinding;
668
	int index = this.indexOfFirstFieldBinding;
708
	if (index == length) { //	restrictiveFlag == FIELD
669
	if (index == length) { //	restrictiveFlag == FIELD
Lines 754-764 Link Here
754
			}
715
			}
755
716
756
			if (field.isStatic()) {
717
			if (field.isStatic()) {
757
				// check if accessing enum static field in initializer
718
				ReferenceBinding declaringClass = field.original().declaringClass;
758
				ReferenceBinding declaringClass = field.declaringClass;
759
				if (declaringClass.isEnum()) {
719
				if (declaringClass.isEnum()) {
760
					MethodScope methodScope = scope.methodScope();
720
					MethodScope methodScope = scope.methodScope();
761
					SourceTypeBinding sourceType = methodScope.enclosingSourceType();
721
					SourceTypeBinding sourceType = methodScope.enclosingSourceType();
722
					if ((this.bits & ASTNode.IsStrictlyAssigned) == 0
723
							&& sourceType == declaringClass
724
							&& methodScope.lastVisibleFieldID >= 0
725
							&& field.id >= methodScope.lastVisibleFieldID
726
							&& (!field.isStatic() || methodScope.isStatic)) {
727
						scope.problemReporter().forwardReference(this, index-1, methodScope.enclosingSourceType());
728
					}					
729
					// check if accessing enum static field in initializer
762
					if ((sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
730
					if ((sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
763
							&& field.constant() == Constant.NotAConstant
731
							&& field.constant() == Constant.NotAConstant
764
							&& !methodScope.isStatic
732
							&& !methodScope.isStatic
Lines 931-948 Link Here
931
			case Binding.VARIABLE : //============only variable===========
899
			case Binding.VARIABLE : //============only variable===========
932
			case Binding.TYPE | Binding.VARIABLE :
900
			case Binding.TYPE | Binding.VARIABLE :
933
				if (this.binding instanceof LocalVariableBinding) {
901
				if (this.binding instanceof LocalVariableBinding) {
934
					LocalVariableBinding local = (LocalVariableBinding) this.binding;
935
					if (!local.isFinal() && ((this.bits & ASTNode.DepthMASK) != 0))
936
						scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding) this.binding, this);
937
					this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
902
					this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
938
					this.bits |= Binding.LOCAL;
903
					this.bits |= Binding.LOCAL;
904
					LocalVariableBinding local = (LocalVariableBinding) this.binding;
905
					if (!local.isFinal() && ((this.bits & ASTNode.DepthMASK) != 0)) {
906
						scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding) this.binding, this);
907
					}
939
					if (local.type != null && (local.type.tagBits & TagBits.HasMissingType) != 0) {
908
					if (local.type != null && (local.type.tagBits & TagBits.HasMissingType) != 0) {
940
						// only complain if field reference (for local, its type got flagged already)
909
						// only complain if field reference (for local, its type got flagged already)
941
						return null;
910
						return null;
942
					}
911
					}
943
					this.resolvedType = getOtherFieldBindings(scope);
912
					this.resolvedType = getOtherFieldBindings(scope);
944
					if (this.resolvedType != null
913
					if (this.resolvedType != null && (this.resolvedType.tagBits & TagBits.HasMissingType) != 0) {
945
							&& (this.resolvedType.tagBits & TagBits.HasMissingType) != 0) {
946
						FieldBinding lastField = this.otherBindings[this.otherBindings.length - 1];
914
						FieldBinding lastField = this.otherBindings[this.otherBindings.length - 1];
947
						scope.problemReporter().invalidField(this, new ProblemFieldBinding(lastField.declaringClass, lastField.name, ProblemReasons.NotFound), this.tokens.length, this.resolvedType.leafComponentType());
915
						scope.problemReporter().invalidField(this, new ProblemFieldBinding(lastField.declaringClass, lastField.name, ProblemReasons.NotFound), this.tokens.length, this.resolvedType.leafComponentType());
948
						return null;
916
						return null;
Lines 950-970 Link Here
950
					return this.resolvedType;
918
					return this.resolvedType;
951
				}
919
				}
952
				if (this.binding instanceof FieldBinding) {
920
				if (this.binding instanceof FieldBinding) {
921
					this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
922
					this.bits |= Binding.FIELD;
953
					FieldBinding fieldBinding = (FieldBinding) this.binding;
923
					FieldBinding fieldBinding = (FieldBinding) this.binding;
954
					MethodScope methodScope = scope.methodScope();
924
					MethodScope methodScope = scope.methodScope();
925
					ReferenceBinding declaringClass = fieldBinding.original().declaringClass;
926
					SourceTypeBinding sourceType = methodScope.enclosingSourceType();
955
					// check for forward references
927
					// check for forward references
956
					if (this.indexOfFirstFieldBinding == 1
928
					if (this.indexOfFirstFieldBinding == 1
957
							&& methodScope.enclosingSourceType() == fieldBinding.original().declaringClass
929
							&& sourceType == declaringClass
958
							&& methodScope.lastVisibleFieldID >= 0
930
							&& methodScope.lastVisibleFieldID >= 0
959
							&& fieldBinding.id >= methodScope.lastVisibleFieldID
931
							&& fieldBinding.id >= methodScope.lastVisibleFieldID
960
							&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
932
							&& (!fieldBinding.isStatic() || methodScope.isStatic)) {
961
						scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
933
						scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType());
962
					}
934
					}
935
					if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & ASTNode.IsStrictlyAssigned) != 0 && this.indexOfFirstFieldBinding == this.tokens.length)) {
936
						scope.problemReporter().deprecatedField(fieldBinding, this);	
937
					}
963
					if (fieldBinding.isStatic()) {
938
					if (fieldBinding.isStatic()) {
964
						ReferenceBinding declaringClass = fieldBinding.declaringClass;
939
						// only last field is actually a write access if any
965
						// check if accessing enum static field in initializer
940
						// check if accessing enum static field in initializer
966
						if (declaringClass.isEnum()) {
941
						if (declaringClass.isEnum()) {
967
							SourceTypeBinding sourceType = methodScope.enclosingSourceType();
968
							if ((sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
942
							if ((sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
969
									&& fieldBinding.constant() == Constant.NotAConstant
943
									&& fieldBinding.constant() == Constant.NotAConstant
970
									&& !methodScope.isStatic
944
									&& !methodScope.isStatic
Lines 972-989 Link Here
972
								scope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
946
								scope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
973
							}
947
							}
974
						}
948
						}
975
					} else if (this.indexOfFirstFieldBinding == 1 && scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
949
						if (this.indexOfFirstFieldBinding > 1
976
						scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
950
								&& fieldBinding.declaringClass != this.actualReceiverType
951
								&& fieldBinding.declaringClass.canBeSeenBy(scope)) {
952
							scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
953
						}						
954
					} else {
955
						if (this.indexOfFirstFieldBinding == 1 && scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
956
							scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
957
						}
958
						//must check for the static status....
959
						if (this.indexOfFirstFieldBinding > 1  //accessing to a field using a type as "receiver" is allowed only with static field
960
								 || scope.methodScope().isStatic) { 	// the field is the first token of the qualified reference....
961
							scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
962
							return null;
963
						 }
977
					}
964
					}
978
					this.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
965
					
979
					this.bits |= Binding.FIELD;
980
981
//						// check for deprecated receiver type
982
//						// deprecation check for receiver type if not first token
983
//						if (indexOfFirstFieldBinding > 1) {
984
//							if (isTypeUseDeprecated(this.actualReceiverType, scope))
985
//								scope.problemReporter().deprecatedType(this.actualReceiverType, this);
986
//						}
987
					this.resolvedType = getOtherFieldBindings(scope);
966
					this.resolvedType = getOtherFieldBindings(scope);
988
					if (this.resolvedType != null
967
					if (this.resolvedType != null
989
							&& (this.resolvedType.tagBits & TagBits.HasMissingType) != 0) {
968
							&& (this.resolvedType.tagBits & TagBits.HasMissingType) != 0) {
(-)src/org/eclipse/jdt/core/tests/compiler/regression/EnumTest.java (-1 / +35 lines)
Lines 5939-5942 Link Here
5939
		false,
5939
		false,
5940
		false);
5940
		false);
5941
	}
5941
	}
5942
}
5942
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=255452
5943
public void test168() {
5944
	this.runNegativeTest(
5945
		new String[] {
5946
			"X.java", // =================
5947
			"enum BadEnum {\n" + 
5948
			"    CRAZY(CRAZY), // <-- illegal forward reference reported by all compilers\n" + 
5949
			"    IMPOSSIBLE(BadEnum.IMPOSSIBLE); // <-- illegal forward reference (javac 1.6 only)\n" + 
5950
			"    private BadEnum(BadEnum self) {\n" + 
5951
			"    }\n" + 
5952
			"}\n" + 
5953
			"public class X {\n" + 
5954
			"    X x1 = new X(x1);//1 - WRONG\n" + 
5955
			"    static X X2 = new X(X.X2);//2 - OK\n" + 
5956
			"    X x3 = new X(this.x3);//3 - OK\n" + 
5957
			"    X(X x) {\n" + 
5958
			"    }\n" + 
5959
			"}\n" + 
5960
			"class Y extends X {\n" + 
5961
			"    X x1 = new X(x1);//4 - WRONG\n" + 
5962
			"    static X X2 = new X(Y.X2);//5 - OK\n" + 
5963
			"    X x3 = new X(this.x3);//6 - OK\n" + 
5964
			"    Y(Y y) {\n" + 
5965
			"            super(y);\n" + 
5966
			"    }\n" + 
5967
			"}\n", // =================
5968
		},
5969
		"----------\n" +
5970
		"1. ERROR in X.java (at line 3)\n" +
5971
		"	private X valueOf(String arg0) { return null; }\n" +
5972
		"	          ^^^^^^^^^^^^^^^^^^^^\n" +
5973
		"The enum X already defines the method valueOf(String) implicitly\n" +
5974
		"----------\n"
5975
	);
5976
}}

Return to bug 255452