X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/QualifiedNameReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/QualifiedNameReference.java index 321949f..26d4107 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/QualifiedNameReference.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/QualifiedNameReference.java @@ -1,20 +1,30 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 + * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation - ******************************************************************************/ + *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor; -import net.sourceforge.phpdt.internal.compiler.impl.*; -import net.sourceforge.phpdt.internal.compiler.codegen.*; -import net.sourceforge.phpdt.internal.compiler.flow.*; -import net.sourceforge.phpdt.internal.compiler.lookup.*; +import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; +import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; +import net.sourceforge.phpdt.internal.compiler.impl.Constant; +import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; +import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope; +import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.SyntheticAccessMethodBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding; + public class QualifiedNameReference extends NameReference { @@ -41,77 +51,64 @@ public class QualifiedNameReference extends NameReference { Assignment assignment, boolean isCompound) { - if (assignment.expression != null) { - flowInfo = - assignment - .expression - .analyseCode(currentScope, flowContext, flowInfo) - .unconditionalInits(); - } // determine the rank until which we now we do not need any actual value for the field access int otherBindingsCount = otherBindings == null ? 0 : otherBindings.length; - int indexOfFirstValueRequired = otherBindingsCount; - while (indexOfFirstValueRequired > 0) { - FieldBinding otherBinding = otherBindings[indexOfFirstValueRequired - 1]; - if (otherBinding.isStatic()) - break; // no longer need any value before this point - indexOfFirstValueRequired--; - } - FieldBinding lastFieldBinding = null; - if ((bits & FIELD) != 0) { - // reading from a field - // check if final blank field - if ((lastFieldBinding = (FieldBinding) binding).isFinal() - && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { - if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) { - currentScope.problemReporter().uninitializedBlankFinalField( - lastFieldBinding, - this); - } - } - } else { - if ((bits & LOCAL) != 0) { - // first binding is a local variable - LocalVariableBinding localBinding; - if (!flowInfo - .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) { - currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); + boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); + switch (bits & RestrictiveFlagMASK) { + case FIELD : // reading a field + lastFieldBinding = (FieldBinding) binding; + if (needValue) { + manageSyntheticReadAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0); + } // check if final blank field + if (lastFieldBinding.isBlankFinal() + && this.otherBindings != null // the last field binding is only assigned + && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { + if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) { + currentScope.problemReporter().uninitializedBlankFinalField( + lastFieldBinding, + this); + } } - if (!flowInfo.isFakeReachable()) - localBinding.used = true; - } + break; +// case LOCAL : +// // first binding is a local variable +// LocalVariableBinding localBinding; +// if (!flowInfo +// .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) { +// currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); +// } +// if (flowInfo.isReachable()) { +// localBinding.useFlag = LocalVariableBinding.USED; +// } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { +// localBinding.useFlag = LocalVariableBinding.FAKE_USED; +// } } - if (indexOfFirstValueRequired == 0) { + + if (needValue) { manageEnclosingInstanceAccessIfNecessary(currentScope); // only for first binding } // all intermediate field accesses are read accesses if (otherBindings != null) { - int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1; - for (int i = start; i < otherBindingsCount; i++) { - if (lastFieldBinding != null) { // could be null if first was a local variable - TypeBinding lastReceiverType; - switch(i){ - case 0 : - lastReceiverType = this.actualReceiverType; - break; - case 1 : - lastReceiverType = ((VariableBinding)binding).type; - break; - default : - lastReceiverType = otherBindings[i-1].type; - } + for (int i = 0; i < otherBindingsCount-1; i++) { + lastFieldBinding = otherBindings[i]; + needValue = !otherBindings[i+1].isStatic(); + if (needValue) { manageSyntheticReadAccessIfNecessary( currentScope, lastFieldBinding, - lastReceiverType, - i); + i == 0 + ? ((VariableBinding)binding).type + : otherBindings[i-1].type, + i + 1); } - lastFieldBinding = otherBindings[i]; } + lastFieldBinding = otherBindings[otherBindingsCount-1]; } + if (isCompound) { if (binding == lastFieldBinding + && lastFieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding) && (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) { currentScope.problemReporter().uninitializedBlankFinalField( @@ -134,25 +131,33 @@ public class QualifiedNameReference extends NameReference { ? 0 : otherBindingsCount); } + + if (assignment.expression != null) { + flowInfo = + assignment + .expression + .analyseCode(currentScope, flowContext, flowInfo) + .unconditionalInits(); + } + // the last field access is a write access if (lastFieldBinding.isFinal()) { // in a context where it can be assigned? - if (currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { + if (lastFieldBinding.isBlankFinal() + && !isCompound + && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding) + && indexOfFirstFieldBinding == 1) { if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) { - if (indexOfFirstFieldBinding == 1) { - // was an implicit reference to the first field binding - currentScope.problemReporter().duplicateInitializationOfBlankFinalField( - lastFieldBinding, - this); - } else { - currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this); - // attempting to assign a non implicit reference - } + currentScope.problemReporter().duplicateInitializationOfBlankFinalField(lastFieldBinding, this); + } else { + flowContext.recordSettingFinal(lastFieldBinding, this); } flowInfo.markAsDefinitelyAssigned(lastFieldBinding); - flowContext.recordSettingFinal(lastFieldBinding, this); } else { currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this); + if (currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { // pretend it got assigned + flowInfo.markAsDefinitelyAssigned(lastFieldBinding); + } } } // equivalent to valuesRequired[maxOtherBindings] @@ -168,6 +173,7 @@ public class QualifiedNameReference extends NameReference { return flowInfo; } + public FlowInfo analyseCode( BlockScope currentScope, FlowContext flowContext, @@ -184,26 +190,16 @@ public class QualifiedNameReference extends NameReference { // determine the rank until which we now we do not need any actual value for the field access int otherBindingsCount = otherBindings == null ? 0 : otherBindings.length; - int indexOfFirstValueRequired; - if (valueRequired) { - indexOfFirstValueRequired = otherBindingsCount; - while (indexOfFirstValueRequired > 0) { - FieldBinding otherBinding = otherBindings[indexOfFirstValueRequired - 1]; - if (otherBinding.isStatic()) - break; // no longer need any value before this point - indexOfFirstValueRequired--; - } - } else { - indexOfFirstValueRequired = otherBindingsCount + 1; - } + + boolean needValue = otherBindingsCount == 0 ? valueRequired : !this.otherBindings[0].isStatic(); switch (bits & RestrictiveFlagMASK) { case FIELD : // reading a field - if (indexOfFirstValueRequired == 0) { + if (needValue) { manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0); } // check if reading a final blank field FieldBinding fieldBinding; - if ((fieldBinding = (FieldBinding) binding).isFinal() + if ((fieldBinding = (FieldBinding) binding).isBlankFinal() && (indexOfFirstFieldBinding == 1) // was an implicit reference to the first field binding && currentScope.allowBlankFinalFieldAssignment(fieldBinding) @@ -211,29 +207,34 @@ public class QualifiedNameReference extends NameReference { currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); } break; - case LOCAL : // reading a local variable - LocalVariableBinding localBinding; - if (!flowInfo - .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) { - currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); - } - if (!flowInfo.isFakeReachable()) - localBinding.used = true; - } - if (indexOfFirstValueRequired == 0) { +// case LOCAL : // reading a local variable +// LocalVariableBinding localBinding; +// if (!flowInfo +// .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) { +// currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); +// } +// if (flowInfo.isReachable()) { +// localBinding.useFlag = LocalVariableBinding.USED; +// } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { +// localBinding.useFlag = LocalVariableBinding.FAKE_USED; +// } + } + if (needValue) { manageEnclosingInstanceAccessIfNecessary(currentScope); // only for first binding } if (otherBindings != null) { - int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1; - for (int i = start; i < otherBindingsCount; i++) { - manageSyntheticReadAccessIfNecessary( - currentScope, - otherBindings[i], - i == 0 - ? ((VariableBinding)binding).type - : otherBindings[i-1].type, - i + 1); + for (int i = 0; i < otherBindingsCount; i++) { + needValue = i < otherBindingsCount-1 ? !otherBindings[i+1].isStatic() : valueRequired; + if (needValue) { + manageSyntheticReadAccessIfNecessary( + currentScope, + otherBindings[i], + i == 0 + ? ((VariableBinding)binding).type + : otherBindings[i-1].type, + i + 1); + } } } return flowInfo; @@ -246,7 +247,7 @@ public class QualifiedNameReference extends NameReference { FieldBinding fieldBinding = (FieldBinding) binding; MethodScope methodScope = scope.methodScope(); if (methodScope.enclosingSourceType() == fieldBinding.declaringClass - && methodScope.fieldDeclarationIndex != methodScope.NotInFieldDecl + && methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl && fieldBinding.id >= methodScope.fieldDeclarationIndex) { if ((!fieldBinding.isStatic() || methodScope.isStatic) && this.indexOfFirstFieldBinding == 1) @@ -256,259 +257,259 @@ public class QualifiedNameReference extends NameReference { bits |= FIELD; return getOtherFieldBindings(scope); } - public void generateAssignment( - BlockScope currentScope, - CodeStream codeStream, - Assignment assignment, - boolean valueRequired) { - - generateReadSequence(currentScope, codeStream, true); - assignment.expression.generateCode(currentScope, codeStream, true); - fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired); - // equivalent to valuesRequired[maxOtherBindings] - if (valueRequired) { - codeStream.generateImplicitConversion(assignment.implicitConversion); - } - } - public void generateCode( - BlockScope currentScope, - CodeStream codeStream, - boolean valueRequired) { - int pc = codeStream.position; - if (constant != NotAConstant) { - if (valueRequired) { - codeStream.generateConstant(constant, implicitConversion); - } - } else { - generateReadSequence(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (lastFieldBinding.declaringClass == null) { // array length - codeStream.arraylength(); - codeStream.generateImplicitConversion(implicitConversion); - } else { - if (lastFieldBinding.constant != NotAConstant) { - // inline the last field constant - codeStream.generateConstant(lastFieldBinding.constant, implicitConversion); - } else { - SyntheticAccessMethodBinding accessor = - syntheticReadAccessors == null - ? null - : syntheticReadAccessors[syntheticReadAccessors.length - 1]; - if (accessor == null) { - if (lastFieldBinding.isStatic()) { - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.getfield(lastFieldBinding); - } - } else { - codeStream.invokestatic(accessor); - } - codeStream.generateImplicitConversion(implicitConversion); - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } - public void generateCompoundAssignment( - BlockScope currentScope, - CodeStream codeStream, - Expression expression, - int operator, - int assignmentImplicitConversion, - boolean valueRequired) { - - generateReadSequence(currentScope, codeStream, true); - SyntheticAccessMethodBinding accessor = - syntheticReadAccessors == null - ? null - : syntheticReadAccessors[syntheticReadAccessors.length - 1]; - if (lastFieldBinding.isStatic()) { - if (accessor == null) { - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.invokestatic(accessor); - } - } else { - codeStream.dup(); - if (accessor == null) { - codeStream.getfield(lastFieldBinding); - } else { - codeStream.invokestatic(accessor); - } - } - // the last field access is a write access - // perform the actual compound operation - int operationTypeID; - if ((operationTypeID = implicitConversion >> 4) == T_String) { - codeStream.generateStringAppend(currentScope, null, expression); - } else { - // promote the array reference to the suitable operation type - codeStream.generateImplicitConversion(implicitConversion); - // generate the increment value (will by itself be promoted to the operation value) - if (expression == IntLiteral.One) { // prefix operation - codeStream.generateConstant(expression.constant, implicitConversion); - } else { - expression.generateCode(currentScope, codeStream, true); - } - // perform the operation - codeStream.sendOperator(operator, operationTypeID); - // cast the value back to the array reference type - codeStream.generateImplicitConversion(assignmentImplicitConversion); - } - // actual assignment - fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired); - // equivalent to valuesRequired[maxOtherBindings] - } - public void generatePostIncrement( - BlockScope currentScope, - CodeStream codeStream, - CompoundAssignment postIncrement, - boolean valueRequired) { - generateReadSequence(currentScope, codeStream, true); - SyntheticAccessMethodBinding accessor = - syntheticReadAccessors == null - ? null - : syntheticReadAccessors[syntheticReadAccessors.length - 1]; - if (lastFieldBinding.isStatic()) { - if (accessor == null) { - codeStream.getstatic(lastFieldBinding); - } else { - codeStream.invokestatic(accessor); - } - } else { - codeStream.dup(); - if (accessor == null) { - codeStream.getfield(lastFieldBinding); - } else { - codeStream.invokestatic(accessor); - } - } - // duplicate the old field value - if (valueRequired) { - if (lastFieldBinding.isStatic()) { - if ((lastFieldBinding.type == LongBinding) - || (lastFieldBinding.type == DoubleBinding)) { - codeStream.dup2(); - } else { - codeStream.dup(); - } - } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] - if ((lastFieldBinding.type == LongBinding) - || (lastFieldBinding.type == DoubleBinding)) { - codeStream.dup2_x1(); - } else { - codeStream.dup_x1(); - } - } - } - codeStream.generateConstant( - postIncrement.expression.constant, - implicitConversion); - codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id); - codeStream.generateImplicitConversion( - postIncrement.assignmentImplicitConversion); - fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, false); - } - /* - * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code - * for a read or write access. - */ - public void generateReadSequence( - BlockScope currentScope, - CodeStream codeStream, - boolean valueRequired) { - // determine the rank until which we now we do not need any actual value for the field access - int otherBindingsCount = this.otherCodegenBindings == null ? 0 : otherCodegenBindings.length; - int indexOfFirstValueRequired; - if (valueRequired) { - indexOfFirstValueRequired = otherBindingsCount; - while (indexOfFirstValueRequired > 0) { - FieldBinding otherBinding = this.otherCodegenBindings[indexOfFirstValueRequired - 1]; - if (otherBinding.isStatic() || otherBinding.constant != NotAConstant) - break; // no longer need any value before this point - indexOfFirstValueRequired--; - } - } else { - indexOfFirstValueRequired = otherBindingsCount + 1; - } - if (indexOfFirstValueRequired == 0) { - switch (bits & RestrictiveFlagMASK) { - case FIELD : - lastFieldBinding = (FieldBinding) this.codegenBinding; - // if first field is actually constant, we can inline it - if (lastFieldBinding.constant != NotAConstant) { - codeStream.generateConstant(lastFieldBinding.constant, 0); - // no implicit conversion - lastFieldBinding = null; // will not generate it again - break; - } - if (!lastFieldBinding.isStatic()) { - if ((bits & DepthMASK) != 0) { - Object[] emulationPath = - currentScope.getExactEmulationPath( - currentScope.enclosingSourceType().enclosingTypeAt( - (bits & DepthMASK) >> DepthSHIFT)); - if (emulationPath == null) { - // internal error, per construction we should have found it - currentScope.problemReporter().needImplementation(); - } else { - codeStream.generateOuterAccess(emulationPath, this, currentScope); - } - } else { - generateReceiver(codeStream); - } - } - break; - case LOCAL : // reading the first local variable - lastFieldBinding = null; - LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; - // regular local variable read - if (localBinding.constant != NotAConstant) { - codeStream.generateConstant(localBinding.constant, 0); - // no implicit conversion - } else { - // outer local? - if ((bits & DepthMASK) != 0) { - // outer local can be reached either through a synthetic arg or a synthetic field - VariableBinding[] path = currentScope.getEmulationPath(localBinding); - if (path == null) { - // emulation was not possible (should not happen per construction) - currentScope.problemReporter().needImplementation(); - } else { - codeStream.generateOuterAccess(path, this, currentScope); - } - } else { - codeStream.load(localBinding); - } - } - } - } else { - lastFieldBinding = null; - } - // all intermediate field accesses are read accesses - // only the last field binding is a write access - if (this.otherCodegenBindings != null) { - int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1; - for (int i = start; i < otherBindingsCount; i++) { - if (lastFieldBinding != null) { - MethodBinding accessor = - syntheticReadAccessors == null ? null : syntheticReadAccessors[i]; - if (accessor == null) - if (lastFieldBinding.isStatic()) - codeStream.getstatic(lastFieldBinding); - else - codeStream.getfield(lastFieldBinding); - else - codeStream.invokestatic(accessor); - } - lastFieldBinding = otherCodegenBindings[i]; - } - } - } - public void generateReceiver(CodeStream codeStream) { - codeStream.aload_0(); - } +// public void generateAssignment( +// BlockScope currentScope, +// CodeStream codeStream, +// Assignment assignment, +// boolean valueRequired) { +// +// generateReadSequence(currentScope, codeStream); +// assignment.expression.generateCode(currentScope, codeStream, true); +// fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired); +// // equivalent to valuesRequired[maxOtherBindings] +// if (valueRequired) { +// codeStream.generateImplicitConversion(assignment.implicitConversion); +// } +// } +// public void generateCode( +// BlockScope currentScope, +// CodeStream codeStream, +// boolean valueRequired) { +// +// int pc = codeStream.position; +// if (constant != NotAConstant) { +// if (valueRequired) { +// codeStream.generateConstant(constant, implicitConversion); +// } +// } else { +// generateReadSequence(currentScope, codeStream); +// if (valueRequired) { +// if (lastFieldBinding.declaringClass == null) { // array length +// codeStream.arraylength(); +// codeStream.generateImplicitConversion(implicitConversion); +// } else { +// if (lastFieldBinding.constant != NotAConstant) { +// if (!lastFieldBinding.isStatic()){ +// codeStream.invokeObjectGetClass(); +// codeStream.pop(); +// } +// // inline the last field constant +// codeStream.generateConstant(lastFieldBinding.constant, implicitConversion); +// } else { +// SyntheticAccessMethodBinding accessor = +// syntheticReadAccessors == null +// ? null +// : syntheticReadAccessors[syntheticReadAccessors.length - 1]; +// if (accessor == null) { +// if (lastFieldBinding.isStatic()) { +// codeStream.getstatic(lastFieldBinding); +// } else { +// codeStream.getfield(lastFieldBinding); +// } +// } else { +// codeStream.invokestatic(accessor); +// } +// codeStream.generateImplicitConversion(implicitConversion); +// } +// } +// } else { +// if (lastFieldBinding != null && !lastFieldBinding.isStatic()){ +// codeStream.invokeObjectGetClass(); // perform null check +// codeStream.pop(); +// } +// +// } +// } +// codeStream.recordPositionsFrom(pc, this.sourceStart); +// } +// public void generateCompoundAssignment( +// BlockScope currentScope, +// CodeStream codeStream, +// Expression expression, +// int operator, +// int assignmentImplicitConversion, +// boolean valueRequired) { +// +// generateReadSequence(currentScope, codeStream); +// SyntheticAccessMethodBinding accessor = +// syntheticReadAccessors == null +// ? null +// : syntheticReadAccessors[syntheticReadAccessors.length - 1]; +// if (lastFieldBinding.isStatic()) { +// if (accessor == null) { +// codeStream.getstatic(lastFieldBinding); +// } else { +// codeStream.invokestatic(accessor); +// } +// } else { +// codeStream.dup(); +// if (accessor == null) { +// codeStream.getfield(lastFieldBinding); +// } else { +// codeStream.invokestatic(accessor); +// } +// } +// // the last field access is a write access +// // perform the actual compound operation +// int operationTypeID; +// if ((operationTypeID = implicitConversion >> 4) == T_String) { +// codeStream.generateStringAppend(currentScope, null, expression); +// } else { +// // promote the array reference to the suitable operation type +// codeStream.generateImplicitConversion(implicitConversion); +// // generate the increment value (will by itself be promoted to the operation value) +// if (expression == IntLiteral.One) { // prefix operation +// codeStream.generateConstant(expression.constant, implicitConversion); +// } else { +// expression.generateCode(currentScope, codeStream, true); +// } +// // perform the operation +// codeStream.sendOperator(operator, operationTypeID); +// // cast the value back to the array reference type +// codeStream.generateImplicitConversion(assignmentImplicitConversion); +// } +// // actual assignment +// fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired); +// // equivalent to valuesRequired[maxOtherBindings] +// } +// public void generatePostIncrement( +// BlockScope currentScope, +// CodeStream codeStream, +// CompoundAssignment postIncrement, +// boolean valueRequired) { +// generateReadSequence(currentScope, codeStream); +// SyntheticAccessMethodBinding accessor = +// syntheticReadAccessors == null +// ? null +// : syntheticReadAccessors[syntheticReadAccessors.length - 1]; +// if (lastFieldBinding.isStatic()) { +// if (accessor == null) { +// codeStream.getstatic(lastFieldBinding); +// } else { +// codeStream.invokestatic(accessor); +// } +// } else { +// codeStream.dup(); +// if (accessor == null) { +// codeStream.getfield(lastFieldBinding); +// } else { +// codeStream.invokestatic(accessor); +// } +// } +// // duplicate the old field value +// if (valueRequired) { +// if (lastFieldBinding.isStatic()) { +// if ((lastFieldBinding.type == LongBinding) +// || (lastFieldBinding.type == DoubleBinding)) { +// codeStream.dup2(); +// } else { +// codeStream.dup(); +// } +// } else { // Stack: [owner][old field value] ---> [old field value][owner][old field value] +// if ((lastFieldBinding.type == LongBinding) +// || (lastFieldBinding.type == DoubleBinding)) { +// codeStream.dup2_x1(); +// } else { +// codeStream.dup_x1(); +// } +// } +// } +// codeStream.generateConstant( +// postIncrement.expression.constant, +// implicitConversion); +// codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id); +// codeStream.generateImplicitConversion( +// postIncrement.assignmentImplicitConversion); +// fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, false); +// } +// /* +// * Generate code for all bindings (local and fields) excluding the last one, which may then be generated code +// * for a read or write access. +// */ +// public void generateReadSequence( +// BlockScope currentScope, +// CodeStream codeStream) { +// +// // determine the rank until which we now we do not need any actual value for the field access +// int otherBindingsCount = this.otherCodegenBindings == null ? 0 : otherCodegenBindings.length; +// +// boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic(); +// switch (bits & RestrictiveFlagMASK) { +// case FIELD : +// lastFieldBinding = (FieldBinding) this.codegenBinding; +// // if first field is actually constant, we can inline it +// if (lastFieldBinding.constant != NotAConstant) { +// break; +// } +// if (needValue && !lastFieldBinding.isStatic()) { +// if ((bits & DepthMASK) != 0) { +// ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT); +// Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); +// codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); +// } else { +// generateReceiver(codeStream); +// } +// } +// break; +// case LOCAL : // reading the first local variable +// if (!needValue) break; // no value needed +// lastFieldBinding = null; +// LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding; +// // regular local variable read +// if (localBinding.constant != NotAConstant) { +// codeStream.generateConstant(localBinding.constant, 0); +// // no implicit conversion +// } else { +// // outer local? +// if ((bits & DepthMASK) != 0) { +// // outer local can be reached either through a synthetic arg or a synthetic field +// VariableBinding[] path = currentScope.getEmulationPath(localBinding); +// codeStream.generateOuterAccess(path, this, localBinding, currentScope); +// } else { +// codeStream.load(localBinding); +// } +// } +// } +// +// // all intermediate field accesses are read accesses +// // only the last field binding is a write access +// if (this.otherCodegenBindings != null) { +// for (int i = 0; i < otherBindingsCount; i++) { +// FieldBinding nextField = this.otherCodegenBindings[i]; +// if (lastFieldBinding != null) { +// needValue = !nextField.isStatic(); +// if (needValue) { +// MethodBinding accessor = +// syntheticReadAccessors == null ? null : syntheticReadAccessors[i]; +// if (accessor == null) { +// if (lastFieldBinding.constant != NotAConstant) { +// if (this.lastFieldBinding != this.codegenBinding && !this.lastFieldBinding.isStatic()) { +// codeStream.invokeObjectGetClass(); // perform null check +// codeStream.pop(); +// } +// codeStream.generateConstant(lastFieldBinding.constant, 0); +// } else if (lastFieldBinding.isStatic()) { +// codeStream.getstatic(lastFieldBinding); +// } else { +// codeStream.getfield(lastFieldBinding); +// } +// } else { +// codeStream.invokestatic(accessor); +// } +// } else { +// if (this.codegenBinding != this.lastFieldBinding && !this.lastFieldBinding.isStatic()){ +// codeStream.invokeObjectGetClass(); // perform null check +// codeStream.pop(); +// } +// } +// } +// this.lastFieldBinding = nextField; +// } +// } +// } +// public void generateReceiver(CodeStream codeStream) { +// codeStream.aload_0(); +// } public TypeBinding getOtherFieldBindings(BlockScope scope) { // At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid) if ((bits & FIELD) != 0) { @@ -536,8 +537,7 @@ public class QualifiedNameReference extends NameReference { int index = indexOfFirstFieldBinding; int length = tokens.length; if (index == length) { // restrictiveFlag == FIELD - constant = - FieldReference.getConstantFor((FieldBinding) binding, false, this, scope, index - 1); + this.constant = FieldReference.getConstantFor((FieldBinding) binding, this, false, scope); return type; } // allocation of the fieldBindings array and its respective constants @@ -546,9 +546,9 @@ public class QualifiedNameReference extends NameReference { otherDepths = new int[otherBindingsLength]; // fill the first constant (the one of the binding) - constant = + this.constant = ((bits & FIELD) != 0) - ? FieldReference.getConstantFor((FieldBinding) binding, false, this, scope, index - 1) + ? FieldReference.getConstantFor((FieldBinding) binding, this, false, scope) : ((VariableBinding) binding).constant; // save first depth, since will be updated by visibility checks of other bindings int firstDepth = (bits & DepthMASK) >> DepthSHIFT; @@ -566,14 +566,20 @@ public class QualifiedNameReference extends NameReference { if (field.isValidBinding()) { if (isFieldUseDeprecated(field, scope)) scope.problemReporter().deprecatedField(field, this); - Constant someConstant = - FieldReference.getConstantFor(field, false, this, scope, place); + Constant someConstant = FieldReference.getConstantFor(field, this, false, scope); // constant propagation can only be performed as long as the previous one is a constant too. - if (constant != NotAConstant) { - constant = someConstant; + if (this.constant != NotAConstant) { + this.constant = someConstant; } + type = field.type; index++; + + if (field.isStatic()) { + // static field accessed through receiver? legal but unoptimal (optional warning) + scope.problemReporter().unnecessaryReceiverForStaticField(this, field); + } + } else { constant = NotAConstant; //don't fill other constants slots... scope.problemReporter().invalidField(this, field, index, type); @@ -589,23 +595,8 @@ public class QualifiedNameReference extends NameReference { if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) { return; } - switch (bits & RestrictiveFlagMASK) { - case FIELD : - FieldBinding fieldBinding; - if ((fieldBinding = (FieldBinding) binding).isStatic() - || (fieldBinding.constant != NotAConstant)) - return; - ReferenceBinding compatibleType = currentScope.enclosingSourceType(); - // the declaringClass of the target binding must be compatible with the enclosing - // type at levels outside - for (int i = 0, depth = (bits & DepthMASK) >> DepthSHIFT; i < depth; i++) { - compatibleType = compatibleType.enclosingType(); - } - currentScope.emulateOuterAccess(compatibleType, false); - // request cascade of accesses - break; - case LOCAL : - currentScope.emulateOuterAccess((LocalVariableBinding) binding); + if ((bits & RestrictiveFlagMASK) == LOCAL) { + currentScope.emulateOuterAccess((LocalVariableBinding) binding); } } public void manageSyntheticReadAccessIfNecessary( @@ -650,25 +641,25 @@ public class QualifiedNameReference extends NameReference { } // 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 1.4 on, field's declaring class is touched if any different from receiver type - if (fieldBinding.declaringClass != lastReceiverType - && !lastReceiverType.isArrayType() - && fieldBinding.declaringClass != null - && fieldBinding.constant == NotAConstant - && ((currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4 - && (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic()) - && fieldBinding.declaringClass.id != T_Object) - || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){ - if (index == 0){ - this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); - } else { - if (this.otherCodegenBindings == this.otherBindings){ - int l = this.otherBindings.length; - System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l); - } - this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); - } - } + // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type +// if (fieldBinding.declaringClass != lastReceiverType +// && !lastReceiverType.isArrayType() +// && fieldBinding.declaringClass != null +// && fieldBinding.constant == NotAConstant +// && ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2 +// && (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic()) +// && fieldBinding.declaringClass.id != T_Object) +// || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){ +// if (index == 0){ +// this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); +// } else { +// if (this.otherCodegenBindings == this.otherBindings){ +// int l = this.otherBindings.length; +// System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l); +// } +// this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); +// } +// } } /* * No need to emulate access to protected fields since not implicitly accessed @@ -696,25 +687,25 @@ public class QualifiedNameReference extends NameReference { } // 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 1.4 on, field's declaring class is touched if any different from receiver type - if (fieldBinding.declaringClass != lastReceiverType - && !lastReceiverType.isArrayType() - && fieldBinding.declaringClass != null - && fieldBinding.constant == NotAConstant - && ((currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4 - && (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic()) - && fieldBinding.declaringClass.id != T_Object) - || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){ - if (fieldBinding == binding){ - this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); - } else { - if (this.otherCodegenBindings == this.otherBindings){ - int l = this.otherBindings.length; - System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l); - } - this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); - } - } + // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type +// if (fieldBinding.declaringClass != lastReceiverType +// && !lastReceiverType.isArrayType() +// && fieldBinding.declaringClass != null +// && fieldBinding.constant == NotAConstant +// && ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2 +// && (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic()) +// && fieldBinding.declaringClass.id != T_Object) +// || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){ +// if (fieldBinding == binding){ +// this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); +// } else { +// if (this.otherCodegenBindings == this.otherBindings){ +// int l = this.otherBindings.length; +// System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l); +// } +// this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType); +// } +// } } /** @@ -730,6 +721,14 @@ public class QualifiedNameReference extends NameReference { } return null; } + public StringBuffer printExpression(int indent, StringBuffer output) { + + for (int i = 0; i < tokens.length; i++) { + if (i > 0) output.append('.'); + output.append(tokens[i]); + } + return output; + } public TypeBinding resolveType(BlockScope scope) { // field and/or local are done before type lookups // the only available value for the restrictiveFlag BEFORE @@ -748,14 +747,14 @@ public class QualifiedNameReference extends NameReference { this); bits &= ~RestrictiveFlagMASK; // clear bits bits |= LOCAL; - return getOtherFieldBindings(scope); + return this.resolvedType = getOtherFieldBindings(scope); } if (binding instanceof FieldBinding) { // check for forward references FieldBinding fieldBinding = (FieldBinding) binding; MethodScope methodScope = scope.methodScope(); if (methodScope.enclosingSourceType() == fieldBinding.declaringClass - && methodScope.fieldDeclarationIndex != methodScope.NotInFieldDecl + && methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl && fieldBinding.id >= methodScope.fieldDeclarationIndex) { if ((!fieldBinding.isStatic() || methodScope.isStatic) && this.indexOfFirstFieldBinding == 1) @@ -763,20 +762,27 @@ public class QualifiedNameReference extends NameReference { } bits &= ~RestrictiveFlagMASK; // clear bits bits |= FIELD; - return getOtherFieldBindings(scope); + + // check for deprecated receiver type + // deprecation check for receiver type if not first token + if (indexOfFirstFieldBinding > 1) { + if (isTypeUseDeprecated(this.actualReceiverType, scope)) + scope.problemReporter().deprecatedType(this.actualReceiverType, this); + } + + return this.resolvedType = getOtherFieldBindings(scope); } // thus it was a type bits &= ~RestrictiveFlagMASK; // clear bits bits |= TYPE; case TYPE : //=============only type ============== - //deprecated test if (isTypeUseDeprecated((TypeBinding) binding, scope)) scope.problemReporter().deprecatedType((TypeBinding) binding, this); - return (TypeBinding) binding; + return this.resolvedType = (TypeBinding) binding; } } //========error cases=============== - return this.reportError(scope); + return this.resolvedType = this.reportError(scope); } public void setFieldIndex(int index) { this.indexOfFirstFieldBinding = index; @@ -798,4 +804,4 @@ public class QualifiedNameReference extends NameReference { public String unboundReferenceErrorName() { return new String(tokens[0]); } -} \ No newline at end of file +}