### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core 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.108 diff -u -r1.108 FieldReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 21 Feb 2007 18:08:14 -0000 1.108 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 14 Mar 2007 00:51:39 -0000 @@ -189,7 +189,8 @@ return; } if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) - || ((implicitConversion & TypeIds.UNBOXING) != 0)) { + || ((implicitConversion & TypeIds.UNBOXING) != 0) + || (this.genericCast != null)) { receiver.generateCode(currentScope, codeStream, !isStatic); pc = codeStream.position; if (this.codegenBinding.declaringClass == null) { // array length @@ -210,8 +211,9 @@ } else { codeStream.invokestatic(syntheticAccessors[READ]); } + // required cast must occur even if no value is required + if (this.genericCast != null) codeStream.checkcast(this.genericCast); if (valueRequired) { - if (this.genericCast != null) codeStream.checkcast(this.genericCast); codeStream.generateImplicitConversion(implicitConversion); } else { if ((implicitConversion & TypeIds.UNBOXING) != 0) { 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.95 diff -u -r1.95 SingleNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 6 Mar 2007 02:38:48 -0000 1.95 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 14 Mar 2007 00:51:40 -0000 @@ -19,13 +19,13 @@ import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; public class SingleNameReference extends NameReference implements OperatorIds { - + public static final int READ = 0; public static final int WRITE = 1; public char[] token; public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor public TypeBinding genericCast; - + public SingleNameReference(char[] source, long pos) { super(); token = source; @@ -33,14 +33,14 @@ sourceEnd = (int) pos; } public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { - + boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0; // compound assignment extra work if (isCompound) { // check the variable part is initialized if blank final switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // reading a field FieldBinding fieldBinding; - if ((fieldBinding = (FieldBinding) binding).isBlankFinal() + if ((fieldBinding = (FieldBinding) binding).isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); @@ -68,7 +68,7 @@ switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); - + FieldBinding fieldBinding = (FieldBinding) binding; ReferenceBinding declaringClass = fieldBinding.declaringClass; // check if accessing enum static field in initializer @@ -82,7 +82,7 @@ && methodScope.isInsideInitializerOrConstructor()) { currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); } - } + } // check if assigning a final field if (fieldBinding.isFinal()) { // inside a context where allowed @@ -90,7 +90,7 @@ if (flowInfo.isPotentiallyAssigned(fieldBinding)) { currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this); } else { - flowContext.recordSettingFinal(fieldBinding, this, flowInfo); + flowContext.recordSettingFinal(fieldBinding, this, flowInfo); } flowInfo.markAsDefinitelyAssigned(fieldBinding); } else { @@ -98,7 +98,7 @@ } } break; - case Binding.LOCAL : // assigning to a local variable + case Binding.LOCAL : // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) binding; if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes bits |= FirstAssignmentToLocal; @@ -113,7 +113,7 @@ } else if (flowInfo.isPotentiallyAssigned(localBinding)) { currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this); } else { - flowContext.recordSettingFinal(localBinding, this, flowInfo); + flowContext.recordSettingFinal(localBinding, this, flowInfo); } } else { currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this); @@ -131,7 +131,7 @@ return analyseCode(currentScope, flowContext, flowInfo, true); } public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { - + switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // reading a field if (valueRequired) { @@ -150,7 +150,7 @@ && methodScope.isInsideInitializerOrConstructor()) { currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); } - } + } // check if reading a final blank field if (fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { @@ -174,11 +174,11 @@ } return flowInfo; } - + public TypeBinding checkFieldAccess(BlockScope scope) { - + FieldBinding fieldBinding = (FieldBinding) binding; - + bits &= ~RestrictiveFlagMASK; // clear bits bits |= Binding.FIELD; MethodScope methodScope = scope.methodScope(); @@ -192,10 +192,10 @@ } } this.constant = fieldBinding.constant(); - + if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) scope.problemReporter().deprecatedField(fieldBinding, this); - + if ((this.bits & IsStrictlyAssigned) == 0 && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass && methodScope.lastVisibleFieldID >= 0 @@ -205,36 +205,36 @@ this.bits |= ASTNode.IgnoreNoEffectAssignCheck; } return fieldBinding.type; - + } - + /** * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding) */ public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) { if (runtimeTimeType == null || compileTimeType == null) - return; + return; if ((bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) { // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast) FieldBinding field = (FieldBinding) this.binding; FieldBinding originalBinding = field.original(); TypeBinding originalType = originalBinding.type; // extra cast needed if method return type is type variable - if (originalBinding != field + if (originalBinding != field && originalType != field.type && runtimeTimeType.id != T_JavaLangObject && (originalType.tagBits & TagBits.HasTypeVariable) != 0) { - TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) + TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) ? compileTimeType // unboxing: checkcast before conversion : runtimeTimeType; this.genericCast = originalType.genericCast(scope.boxing(targetType)); - } + } } super.computeConversion(scope, runtimeTimeType, compileTimeType); - } + } public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) { - + // optimizing assignment like: i = i + 1 or i = 1 + i if (assignment.expression.isCompactableOperation()) { BinaryExpression operation = (BinaryExpression) assignment.expression; @@ -245,9 +245,9 @@ variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); - } + } return; - } + } if ((operation.right instanceof SingleNameReference) && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations && ((variableReference = (SingleNameReference) operation.right).binding == binding) @@ -258,7 +258,7 @@ variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); - } + } return; } } @@ -309,14 +309,14 @@ } return; } - // 26903, need extra cast to store null in array local var - if (localBinding.type.isArrayType() + // 26903, need extra cast to store null in array local var + if (localBinding.type.isArrayType() && (assignment.expression.resolvedType == TypeBinding.NULL // arrayLoc = null || ((assignment.expression instanceof CastExpression) // arrayLoc = (type[])null && (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){ - codeStream.checkcast(localBinding.type); + codeStream.checkcast(localBinding.type); } - + // normal local assignment (since cannot store in outer local which are final locations) codeStream.store(localBinding, valueRequired); if ((bits & FirstAssignmentToLocal) != 0) { // for local variable debug attributes @@ -354,14 +354,15 @@ break; } } - // managing private access + // managing private access if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) { codeStream.getstatic(fieldBinding); } else { codeStream.invokestatic(syntheticAccessors[READ]); } + // required cast must occur even if no value is required + if (this.genericCast != null) codeStream.checkcast(this.genericCast); if (valueRequired) { - if (this.genericCast != null) codeStream.checkcast(this.genericCast); codeStream.generateImplicitConversion(implicitConversion); } else { if ((implicitConversion & TypeIds.UNBOXING) != 0) { @@ -376,9 +377,11 @@ default : codeStream.pop(); } - } + } } else { - if (!valueRequired && ((implicitConversion & TypeIds.UNBOXING) == 0)) { + if (!valueRequired + && ((implicitConversion & TypeIds.UNBOXING) == 0) + && this.genericCast == null) { // required cast must occur even if no value is required // if no valueRequired, optimize out entire gen break; } @@ -390,15 +393,25 @@ } else { generateReceiver(codeStream); } - // managing private access + // managing private access if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) { codeStream.getfield(fieldBinding); } else { codeStream.invokestatic(syntheticAccessors[READ]); } // managing generic cast - if (this.genericCast != null) codeStream.checkcast(this.genericCast); + if (this.genericCast != null) codeStream.checkcast(this.genericCast); codeStream.generateImplicitConversion(implicitConversion); + if (!valueRequired) { + switch (fieldBinding.type.id) { + case T_long : + case T_double : + codeStream.pop2(); + break; + default : + codeStream.pop(); + } + } } break; case Binding.LOCAL : // reading a local @@ -415,7 +428,6 @@ } codeStream.generateImplicitConversion(implicitConversion); } else if ((implicitConversion & TypeIds.UNBOXING) != 0) { - // outer local? if ((bits & DepthMASK) != 0) { // outer local can be reached either through a synthetic arg or a synthetic field @@ -426,10 +438,13 @@ codeStream.load(localBinding); } codeStream.generateImplicitConversion(implicitConversion); - if ((localBinding.type == TypeBinding.LONG) || (localBinding.type == TypeBinding.DOUBLE)) { - codeStream.pop2(); - } else { - codeStream.pop(); + switch (localBinding.type.id) { + case T_long : + case T_double : + codeStream.pop2(); + break; + default : + codeStream.pop(); } } } @@ -443,14 +458,14 @@ * are optimized in one access: e.g "a = a + 1" optimized into "a++". */ public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { - + this.generateCompoundAssignment( - currentScope, - codeStream, + currentScope, + codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], expression, - operator, - assignmentImplicitConversion, + operator, + assignmentImplicitConversion, valueRequired); } /* @@ -497,7 +512,7 @@ codeStream.store(localBinding, false); return; case T_int : - if (((assignConstant = expression.constant) != Constant.NotAConstant) + if (((assignConstant = expression.constant) != Constant.NotAConstant) && (assignConstant.typeID() != T_float) // only for integral types && (assignConstant.typeID() != T_double) && ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value @@ -526,11 +541,11 @@ case T_JavaLangString : case T_JavaLangObject : case T_undefined : - // we enter here if the single name reference is a field of type java.lang.String or if the type of the + // we enter here if the single name reference is a field of type java.lang.String or if the type of the // operation is java.lang.Object // For example: o = o + ""; // where the compiled type of o is java.lang.Object. codeStream.generateStringConcatenationAppend(currentScope, null, expression); - // no need for generic cast on previous #getfield since using Object string buffer methods. + // no need for generic cast on previous #getfield since using Object string buffer methods. break; default : // promote the array reference to the suitable operation type @@ -539,10 +554,10 @@ codeStream.generateImplicitConversion(this.implicitConversion); // generate the increment value (will by itself be promoted to the operation value) if (expression == IntLiteral.One){ // prefix operation - codeStream.generateConstant(expression.constant, this.implicitConversion); + codeStream.generateConstant(expression.constant, this.implicitConversion); } else { expression.generateCode(currentScope, codeStream, true); - } + } // perform the operation codeStream.sendOperator(operator, operationTypeID); // cast the value back to the array reference type @@ -566,7 +581,7 @@ codeStream.store(localBinding, false); } } - + public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) { switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field @@ -607,14 +622,14 @@ } } } - if (this.genericCast != null) + if (this.genericCast != null) codeStream.checkcast(this.genericCast); - codeStream.generateImplicitConversion(this.implicitConversion); + codeStream.generateImplicitConversion(this.implicitConversion); codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); fieldStore(codeStream, fieldBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], false); - // no need for generic cast + // no need for generic cast return; case Binding.LOCAL : // assigning to a local variable LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; @@ -641,16 +656,16 @@ codeStream.generateConstant(postIncrement.expression.constant, implicitConversion); codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); - + codeStream.store(localBinding, false); } } - } - + } + public void generateReceiver(CodeStream codeStream) { codeStream.aload_0(); } - + /** * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments() */ @@ -671,26 +686,26 @@ } return null; } - + public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { - + if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { //If inlinable field, forget the access emulation, the code gen will directly target it if (((bits & DepthMASK) == 0) || (constant != Constant.NotAConstant)) return; - + if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) { currentScope.emulateOuterAccess((LocalVariableBinding) binding); } } } public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) { - + if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; - + //If inlinable field, forget the access emulation, the code gen will directly target it if (constant != Constant.NotAConstant) return; - + if ((bits & Binding.FIELD) != 0) { FieldBinding fieldBinding = (FieldBinding) binding; FieldBinding codegenField = fieldBinding.original(); @@ -701,7 +716,7 @@ && codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) { if (syntheticAccessors == null) syntheticAccessors = new MethodBinding[2]; - syntheticAccessors[isReadAccess ? READ : WRITE] = + syntheticAccessors[isReadAccess ? READ : WRITE] = ((SourceTypeBinding)currentScope.enclosingSourceType(). enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess); currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess); @@ -710,7 +725,7 @@ // if the binding declaring class is not visible, need special action // for runtime compatibility on 1.2 VMs : change the declaring class of the binding // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type - // and not from Object or implicit static field access. + // and not from Object or implicit static field access. if (fieldBinding.declaringClass != this.actualReceiverType && !this.actualReceiverType.isArrayType() && fieldBinding.declaringClass != null // array.length @@ -720,13 +735,13 @@ && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic()) && fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields || !fieldBinding.declaringClass.canBeSeenBy(currentScope)) { - - this.codegenBinding = + + this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding( - codegenField, + codegenField, (ReferenceBinding)this.actualReceiverType.erasure()); } - } + } } } @@ -747,7 +762,7 @@ return FlowInfo.UNKNOWN; } } - return FlowInfo.NON_NULL; // never get there + return FlowInfo.NON_NULL; // never get there } /** @@ -755,7 +770,7 @@ */ public TypeBinding postConversionType(Scope scope) { TypeBinding convertedType = this.resolvedType; - if (this.genericCast != null) + if (this.genericCast != null) convertedType = this.genericCast; int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4; switch (runtimeType) { @@ -784,19 +799,19 @@ convertedType = TypeBinding.DOUBLE; break; default : - } + } if ((this.implicitConversion & BOXING) != 0) { convertedType = scope.environment().computeBoxingType(convertedType); } return convertedType; } - + public StringBuffer printExpression(int indent, StringBuffer output){ - + return output.append(token); } public TypeBinding reportError(BlockScope scope) { - + //=====error cases======= constant = Constant.NotAConstant; if (binding instanceof ProblemFieldBinding) { @@ -808,10 +823,10 @@ } return null; } - + public TypeBinding resolveType(BlockScope scope) { - // for code gen, harm the restrictiveFlag - + // for code gen, harm the restrictiveFlag + if (this.actualReceiverType != null) { this.binding = scope.getField(this.actualReceiverType, token, this); } else { @@ -834,7 +849,7 @@ TypeBinding fieldType = variable.type; if ((this.bits & IsStrictlyAssigned) == 0) { constant = variable.constant(); - if (fieldType != null) + if (fieldType != null) fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access } else { constant = Constant.NotAConstant; @@ -848,12 +863,12 @@ } // perform capture conversion if read access TypeBinding fieldType = checkFieldAccess(scope); - return this.resolvedType = - (((this.bits & IsStrictlyAssigned) == 0) + return this.resolvedType = + (((this.bits & IsStrictlyAssigned) == 0) ? fieldType.capture(scope, this.sourceEnd) : fieldType); } - + // thus it was a type bits &= ~RestrictiveFlagMASK; // clear bits bits |= Binding.TYPE; @@ -867,23 +882,23 @@ return this.resolvedType = type; } } - + // error scenarii return this.resolvedType = this.reportError(scope); } - + public void traverse(ASTVisitor visitor, BlockScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } - + public void traverse(ASTVisitor visitor, ClassScope scope) { visitor.visit(this, scope); visitor.endVisit(this, scope); } public String unboundReferenceErrorName(){ - + return new String(token); - } + } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java,v retrieving revision 1.120 diff -u -r1.120 MessageSend.java --- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 6 Mar 2007 02:38:48 -0000 1.120 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 14 Mar 2007 00:51:39 -0000 @@ -144,11 +144,11 @@ } else { codeStream.invokestatic(syntheticAccessor); } - // operation on the returned value + // required cast must occur even if no value is required + if (this.valueCast != null) codeStream.checkcast(this.valueCast); + if (valueRequired){ // implicit conversion if necessary - if (this.valueCast != null) - codeStream.checkcast(this.valueCast); codeStream.generateImplicitConversion(implicitConversion); } else { // pop return value if any