### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java,v retrieving revision 1.159 diff -u -r1.159 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 27 Jun 2008 16:04:02 -0000 1.159 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 15 Sep 2008 21:17:18 -0000 @@ -44,6 +44,7 @@ private final static int METHOD_EMUL = 0; private final static int FIELD_EMUL = 1; private final static int CLASS_LITERAL_EMUL = 2; + /** @deprecated */ private final static int RECEIVER_TYPE_EMUL = 3; private final static int MAX_SYNTHETICS = 4; @@ -1064,6 +1065,7 @@ public ReferenceBinding[] memberTypes() { return this.memberTypes; } +/** @deprecated */ public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; @@ -1082,6 +1084,7 @@ } return updatedField; } +/** @deprecated */ public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) { if (this.synthetics == null) this.synthetics = new HashMap[MAX_SYNTHETICS]; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java,v retrieving revision 1.340 diff -u -r1.340 Scope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java 9 Sep 2008 18:40:55 -0000 1.340 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java 15 Sep 2008 21:17:11 -0000 @@ -23,7 +23,7 @@ import org.eclipse.jdt.internal.compiler.util.ObjectVector; import org.eclipse.jdt.internal.compiler.util.SimpleSet; -public abstract class Scope implements TypeConstants, TypeIds { +public abstract class Scope { /* Scope kinds */ public final static int BLOCK_SCOPE = 1; @@ -781,7 +781,7 @@ // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) { if (argumentTypes == Binding.NO_PARAMETERS - && CharOperation.equals(selector, GETCLASS) + && CharOperation.equals(selector, TypeConstants.GETCLASS) && exactMethod.returnType.isParameterizedType()/*1.5*/) { return ParameterizedMethodBinding.instantiateGetClass(receiverType, exactMethod, this); } @@ -832,7 +832,7 @@ if (leafType instanceof ReferenceBinding) if (!((ReferenceBinding) leafType).canBeSeenBy(this)) return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ProblemReasons.ReceiverTypeNotVisible); - if (CharOperation.equals(fieldName, LENGTH)) { + if (CharOperation.equals(fieldName, TypeConstants.LENGTH)) { if ((leafType.tagBits & TagBits.HasMissingType) != 0) { return new ProblemFieldBinding(ArrayBinding.ArrayLength, null, fieldName, ProblemReasons.NotFound); } @@ -1314,19 +1314,12 @@ if (argumentTypes == Binding.NO_PARAMETERS) { switch (selector[0]) { case 'c': - if (CharOperation.equals(selector, CLONE)) { - return new UpdatedMethodBinding( - compilerOptions().targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0 - (methodBinding.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic, - CLONE, - methodBinding.returnType, - argumentTypes, - null, - object); + if (CharOperation.equals(selector, TypeConstants.CLONE)) { + return environment().computeArrayClone(methodBinding); } break; case 'g': - if (CharOperation.equals(selector, GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { + if (CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this); } break; @@ -1854,7 +1847,7 @@ } // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (argumentTypes == Binding.NO_PARAMETERS - && CharOperation.equals(selector, GETCLASS) + && CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this); } @@ -2014,65 +2007,65 @@ public final ReferenceBinding getJavaIoSerializable() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_IO_SERIALIZABLE); - return unitScope.environment.getResolvedType(JAVA_IO_SERIALIZABLE, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_IO_SERIALIZABLE); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_IO_SERIALIZABLE, this); } public final ReferenceBinding getJavaLangAnnotationAnnotation() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_ANNOTATION_ANNOTATION); - return unitScope.environment.getResolvedType(JAVA_LANG_ANNOTATION_ANNOTATION, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION, this); } public final ReferenceBinding getJavaLangAssertionError() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_ASSERTIONERROR); - return unitScope.environment.getResolvedType(JAVA_LANG_ASSERTIONERROR, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ASSERTIONERROR); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ASSERTIONERROR, this); } public final ReferenceBinding getJavaLangClass() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_CLASS); - return unitScope.environment.getResolvedType(JAVA_LANG_CLASS, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLASS); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_CLASS, this); } public final ReferenceBinding getJavaLangCloneable() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_CLONEABLE); - return unitScope.environment.getResolvedType(JAVA_LANG_CLONEABLE, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLONEABLE); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_CLONEABLE, this); } public final ReferenceBinding getJavaLangEnum() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_ENUM); - return unitScope.environment.getResolvedType(JAVA_LANG_ENUM, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ENUM); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ENUM, this); } public final ReferenceBinding getJavaLangIterable() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_ITERABLE); - return unitScope.environment.getResolvedType(JAVA_LANG_ITERABLE, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ITERABLE); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_ITERABLE, this); } public final ReferenceBinding getJavaLangObject() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_OBJECT); - return unitScope.environment.getResolvedType(JAVA_LANG_OBJECT, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_OBJECT); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, this); } public final ReferenceBinding getJavaLangString() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_STRING); - return unitScope.environment.getResolvedType(JAVA_LANG_STRING, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_STRING); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_STRING, this); } public final ReferenceBinding getJavaLangThrowable() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_LANG_THROWABLE); - return unitScope.environment.getResolvedType(JAVA_LANG_THROWABLE, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_THROWABLE); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_LANG_THROWABLE, this); } public final ReferenceBinding getJavaUtilIterator() { CompilationUnitScope unitScope = compilationUnitScope(); - unitScope.recordQualifiedReference(JAVA_UTIL_ITERATOR); - return unitScope.environment.getResolvedType(JAVA_UTIL_ITERATOR, this); + unitScope.recordQualifiedReference(TypeConstants.JAVA_UTIL_ITERATOR); + return unitScope.environment.getResolvedType(TypeConstants.JAVA_UTIL_ITERATOR, this); } /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType. @@ -2114,7 +2107,7 @@ // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type) if (argumentTypes == Binding.NO_PARAMETERS - && CharOperation.equals(selector, GETCLASS) + && CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) { return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this); } @@ -3038,8 +3031,8 @@ case 0 : return TypeBinding.VOID; case 1 : return mecs[0]; case 2 : - if ((commonDim == 0 ? mecs[1].id : mecs[1].leafComponentType().id) == T_JavaLangObject) return mecs[0]; - if ((commonDim == 0 ? mecs[0].id : mecs[0].leafComponentType().id) == T_JavaLangObject) return mecs[1]; + if ((commonDim == 0 ? mecs[1].id : mecs[1].leafComponentType().id) == TypeIds.T_JavaLangObject) return mecs[0]; + if ((commonDim == 0 ? mecs[0].id : mecs[0].leafComponentType().id) == TypeIds.T_JavaLangObject) return mecs[1]; } TypeBinding[] otherBounds = new TypeBinding[count - 1]; int rank = 0; @@ -3118,7 +3111,7 @@ if (dim > 0) { leafType = typeToVisit.leafComponentType(); switch(leafType.id) { - case T_JavaLangObject: + case TypeIds.T_JavaLangObject: if (dim > 1) { // Object[][] supertype is Object[] TypeBinding elementType = ((ArrayBinding)typeToVisit).elementsType(); if (!typesToVisit.contains(elementType)) { @@ -3128,14 +3121,14 @@ continue; } //$FALL-THROUGH$ - case T_byte: - case T_short: - case T_char: - case T_boolean: - case T_int: - case T_long: - case T_float: - case T_double: + case TypeIds.T_byte: + case TypeIds.T_short: + case TypeIds.T_char: + case TypeIds.T_boolean: + case TypeIds.T_int: + case TypeIds.T_long: + case TypeIds.T_float: + case TypeIds.T_double: TypeBinding superType = getJavaIoSerializable(); if (!typesToVisit.contains(superType)) { typesToVisit.add(superType); @@ -3254,7 +3247,7 @@ TypeBinding erasedSuperType = erasedSuperTypes[j]; if (erasedSuperType == null) continue nextSuperType; TypeBinding match; - if (erasedSuperType == otherType || erasedSuperType.id == T_JavaLangObject && otherType.isInterface()) { + if (erasedSuperType == otherType || erasedSuperType.id == TypeIds.T_JavaLangObject && otherType.isInterface()) { match = erasedSuperType; } else { if (erasedSuperType.isArrayType()) { @@ -3302,14 +3295,14 @@ TypeBinding otherType = erasedSuperTypes[j]; if (otherType == null) continue nextOtherType; if (erasedSuperType instanceof ReferenceBinding) { - if (otherType.id == T_JavaLangObject && erasedSuperType.isInterface()) continue nextOtherType; // keep Object for an interface + if (otherType.id == TypeIds.T_JavaLangObject && erasedSuperType.isInterface()) continue nextOtherType; // keep Object for an interface if (erasedSuperType.findSuperTypeOriginatingFrom(otherType) != null) { erasedSuperTypes[j] = null; // discard non minimal supertype remaining--; } } else if (erasedSuperType.isArrayType()) { if (otherType.isArrayType() // keep Object[...] for an interface array (same dimensions) - && otherType.leafComponentType().id == T_JavaLangObject + && otherType.leafComponentType().id == TypeIds.T_JavaLangObject && otherType.dimensions() == erasedSuperType.dimensions() && erasedSuperType.leafComponentType().isInterface()) continue nextOtherType; if (erasedSuperType.findSuperTypeOriginatingFrom(otherType) != null) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java,v retrieving revision 1.98 diff -u -r1.98 LookupEnvironment.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java 27 Jun 2008 16:04:02 -0000 1.98 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java 15 Sep 2008 21:16:47 -0000 @@ -62,6 +62,8 @@ private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4]; private MethodVerifier verifier; + public MethodBinding arrayClone; + final static int BUILD_FIELDS_AND_METHODS = 4; final static int BUILD_TYPE_HIERARCHY = 1; final static int CHECK_AND_SET_IMPORTS = 2; @@ -251,7 +253,19 @@ parsedUnit.scope.buildFieldsAndMethods(); this.unitBeingCompleted = null; } - +public MethodBinding computeArrayClone(MethodBinding objectClone) { + if (this.arrayClone == null) { + this.arrayClone = new MethodBinding( + (objectClone.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic, + TypeConstants.CLONE, + objectClone.returnType, + Binding.NO_PARAMETERS, + Binding.NO_EXCEPTIONS, // no exception for array specific method + (ReferenceBinding)objectClone.returnType); + } + return this.arrayClone; + +} public TypeBinding computeBoxingType(TypeBinding type) { TypeBinding boxedType; switch (type.id) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java,v retrieving revision 1.46 diff -u -r1.46 TypeConstants.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java 5 Sep 2008 11:22:41 -0000 1.46 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java 15 Sep 2008 21:17:18 -0000 @@ -73,6 +73,7 @@ char[] UPPER_LOCAL_VARIABLE = "LOCAL_VARIABLE".toCharArray(); //$NON-NLS-1$ char[] UPPER_ANNOTATION_TYPE = "ANNOTATION_TYPE".toCharArray(); //$NON-NLS-1$ char[] UPPER_PACKAGE = "PACKAGE".toCharArray(); //$NON-NLS-1$ + char[] ITERATOR = "iterator".toCharArray(); //$NON-NLS-1$ // Constant compound names char[][] JAVA_LANG = {JAVA, LANG}; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java,v retrieving revision 1.119 diff -u -r1.119 CompilationUnitScope.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java 27 Jun 2008 16:04:02 -0000 1.119 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java 15 Sep 2008 21:16:40 -0000 @@ -154,7 +154,7 @@ int numberOfImports = numberOfStatements + 1; for (int i = 0; i < numberOfStatements; i++) { ImportReference importReference = this.referenceContext.imports[i]; - if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) { + if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(TypeConstants.JAVA_LANG, importReference.tokens) && !importReference.isStatic()) { numberOfImports--; break; } @@ -313,7 +313,7 @@ int numberOfImports = numberOfStatements + 1; for (int i = 0; i < numberOfStatements; i++) { ImportReference importReference = this.referenceContext.imports[i]; - if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(JAVA_LANG, importReference.tokens) && !importReference.isStatic()) { + if (((importReference.bits & ASTNode.OnDemand) != 0) && CharOperation.equals(TypeConstants.JAVA_LANG, importReference.tokens) && !importReference.isStatic()) { numberOfImports--; break; } @@ -569,21 +569,21 @@ // initialize the default imports if necessary... share the default java.lang.* import if (this.environment.defaultImports != null) return this.environment.defaultImports; - Binding importBinding = this.environment.getTopLevelPackage(JAVA); + Binding importBinding = this.environment.getTopLevelPackage(TypeConstants.JAVA); if (importBinding != null) - importBinding = ((PackageBinding) importBinding).getTypeOrPackage(JAVA_LANG[1]); + importBinding = ((PackageBinding) importBinding).getTypeOrPackage(TypeConstants.JAVA_LANG[1]); if (importBinding == null || !importBinding.isValidBinding()) { // create a proxy for the missing BinaryType problemReporter().isClassPathCorrect( - JAVA_LANG_OBJECT, + TypeConstants.JAVA_LANG_OBJECT, this.referenceContext, this.environment.missingClassFileLocation); - BinaryTypeBinding missingObject = this.environment.createMissingType(null, JAVA_LANG_OBJECT); + BinaryTypeBinding missingObject = this.environment.createMissingType(null, TypeConstants.JAVA_LANG_OBJECT); importBinding = missingObject.fPackage; } - return this.environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)}; + return this.environment.defaultImports = new ImportBinding[] {new ImportBinding(TypeConstants.JAVA_LANG, true, importBinding, null)}; } // NOT Public API public final Binding getImport(char[][] compoundName, boolean onDemand, boolean isStaticImport) { Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java,v retrieving revision 1.103 diff -u -r1.103 MethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 12 Sep 2008 15:54:13 -0000 1.103 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 15 Sep 2008 21:16:51 -0000 @@ -391,14 +391,6 @@ return uniqueKey; } -/* - * Answer the declaring class to use in the constant pool - * may not be a reference binding (see subtypes) - */ -public TypeBinding constantPoolDeclaringClass() { - return this.declaringClass; -} - /* Answer the receiver's constant pool name. * * for constructors Index: compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java =================================================================== RCS file: compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java diff -N compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java 27 Jun 2008 16:04:02 -0000 1.6 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jdt.internal.compiler.lookup; - -public class UpdatedMethodBinding extends MethodBinding { - - public TypeBinding updatedDeclaringClass; - - public UpdatedMethodBinding(TypeBinding updatedDeclaringClass, int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) { - super(modifiers, selector, returnType, args, exceptions, declaringClass); - this.updatedDeclaringClass = updatedDeclaringClass; - } - - public TypeBinding constantPoolDeclaringClass() { - return this.updatedDeclaringClass; - } -} Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.164 diff -u -r1.164 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 7 Jul 2008 17:08:07 -0000 1.164 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 15 Sep 2008 21:16:36 -0000 @@ -2245,7 +2245,7 @@ FieldBinding fieldBinding = (FieldBinding) mappingSequence[i]; getfield(fieldBinding); } else { - invokestatic((MethodBinding) mappingSequence[i]); + invokestatic((MethodBinding) mappingSequence[i], null /* default declaringClass */); } } } @@ -2312,9 +2312,7 @@ * @param accessBinding the access method binding to generate */ public void generateSyntheticBodyForConstructorAccess(SyntheticMethodBinding accessBinding) { - initializeMaxLocals(accessBinding); - MethodBinding constructorBinding = accessBinding.targetMethod; TypeBinding[] parameters = constructorBinding.parameters; int length = parameters.length; @@ -2359,7 +2357,7 @@ resolvedPosition++; } } - invokespecial(constructorBinding); + invokespecial(constructorBinding, null /* default declaringClass */); return_(); } //static X valueOf(String name) { @@ -2451,7 +2449,6 @@ return_(); } public void generateSyntheticBodyForMethodAccess(SyntheticMethodBinding accessMethod) { - initializeMaxLocals(accessMethod); MethodBinding targetMethod = accessMethod.targetMethod; TypeBinding[] parameters = targetMethod.parameters; @@ -2482,18 +2479,18 @@ resolvedPosition++; } if (targetMethod.isStatic()) - invokestatic(targetMethod); + invokestatic(targetMethod, null /* default declaringClass */); else { if (targetMethod.isConstructor() || targetMethod.isPrivate() // qualified super "X.super.foo()" targets methods from superclass || accessMethod.purpose == SyntheticMethodBinding.SuperMethodAccess){ - invokespecial(targetMethod); + invokespecial(targetMethod, null /* default declaringClass */); } else { if (targetMethod.declaringClass.isInterface()) { // interface or annotation type - invokeinterface(targetMethod); + invokeinterface(targetMethod, null /* default declaringClass */); } else { - invokevirtual(targetMethod); + invokevirtual(targetMethod, accessMethod.declaringClass); } } } @@ -3845,8 +3842,9 @@ ConstantPool.Ordinal, ConstantPool.OrdinalSignature); } -public void invokeinterface(MethodBinding methodBinding) { +public void invokeinterface(MethodBinding methodBinding, TypeBinding declaringClass) { if (DEBUG) System.out.println(this.position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$ + if (declaringClass == null) declaringClass = methodBinding.declaringClass; this.countLabels = 0; // initialized to 1 to take into account this immediately int argCount = 1; @@ -3858,7 +3856,7 @@ this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_invokeinterface; writeUnsignedShort( this.constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass(), + declaringClass, methodBinding.selector, methodBinding.signature(this.classFile), true)); @@ -4143,8 +4141,9 @@ ConstantPool.GetClass, ConstantPool.GetClassSignature); } -public void invokespecial(MethodBinding methodBinding) { +public void invokespecial(MethodBinding methodBinding, TypeBinding declaringClass) { if (DEBUG) System.out.println(this.position + "\t\tinvokespecial:"+methodBinding); //$NON-NLS-1$ + if (declaringClass == null) declaringClass = methodBinding.declaringClass; this.countLabels = 0; // initialized to 1 to take into account this immediately int argCount = 1; @@ -4156,15 +4155,15 @@ this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_invokespecial; writeUnsignedShort( this.constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass(), + declaringClass, methodBinding.selector, methodBinding.signature(this.classFile), false)); if (methodBinding.isConstructor()) { - final ReferenceBinding declaringClass = methodBinding.declaringClass; if (declaringClass.isNestedType()) { + final ReferenceBinding nestedType = (ReferenceBinding) declaringClass; // enclosing instances - TypeBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes(); + TypeBinding[] syntheticArgumentTypes = nestedType.syntheticEnclosingInstanceTypes(); if (syntheticArgumentTypes != null) { for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) { if (((id = syntheticArgumentTypes[i].id) == TypeIds.T_double) || (id == TypeIds.T_long)) { @@ -4175,7 +4174,7 @@ } } // outer local variables - SyntheticArgumentBinding[] syntheticArguments = declaringClass.syntheticOuterLocalVariables(); + SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables(); if (syntheticArguments != null) { for (int i = 0, max = syntheticArguments.length; i < max; i++) { if (((id = syntheticArguments[i].type.id) == TypeIds.T_double) || (id == TypeIds.T_long)) { @@ -4206,8 +4205,9 @@ if (this.stackDepth > this.stackMax) this.stackMax = this.stackDepth; } -public void invokestatic(MethodBinding methodBinding) { +public void invokestatic(MethodBinding methodBinding, TypeBinding declaringClass) { if (DEBUG) System.out.println(this.position + "\t\tinvokestatic:"+methodBinding); //$NON-NLS-1$ + if (declaringClass == null) declaringClass = methodBinding.declaringClass; // initialized to 0 to take into account that there is no this for // a static method this.countLabels = 0; @@ -4220,7 +4220,7 @@ this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_invokestatic; writeUnsignedShort( this.constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass(), + declaringClass, methodBinding.selector, methodBinding.signature(this.classFile), false)); @@ -4481,8 +4481,9 @@ ConstantPool.GetMessage, ConstantPool.GetMessageSignature); } -public void invokevirtual(MethodBinding methodBinding) { +public void invokevirtual(MethodBinding methodBinding,TypeBinding declaringClass) { if (DEBUG) System.out.println(this.position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$ + if (declaringClass == null) declaringClass = methodBinding.declaringClass; this.countLabels = 0; // initialized to 1 to take into account this immediately int argCount = 1; @@ -4494,7 +4495,7 @@ this.bCodeStream[this.classFileOffset++] = Opcodes.OPC_invokevirtual; writeUnsignedShort( this.constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass(), + declaringClass, methodBinding.selector, methodBinding.signature(this.classFile), false)); 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.119 diff -u -r1.119 FieldReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 26 Aug 2008 14:35:24 -0000 1.119 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java 15 Sep 2008 21:15:44 -0000 @@ -233,7 +233,7 @@ codeStream.getfield(this.codegenBinding); } } else { - codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } // required cast must occur even if no value is required if (this.genericCast != null) codeStream.checkcast(this.genericCast); @@ -262,7 +262,7 @@ if (accessor == null) { codeStream.getstatic(this.codegenBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } switch (this.codegenBinding.type.id) { case T_long : @@ -295,14 +295,14 @@ if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { codeStream.getstatic(this.codegenBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } else { codeStream.dup(); if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { codeStream.getfield(this.codegenBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } int operationTypeID; @@ -346,14 +346,14 @@ if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { codeStream.getstatic(this.codegenBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } else { codeStream.dup(); if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) { codeStream.getfield(this.codegenBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[FieldReference.READ], null /* default declaringClass */); } } TypeBinding operandType; Index: compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java,v retrieving revision 1.28 diff -u -r1.28 Reference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java 28 Mar 2006 20:29:56 -0000 1.28 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java 15 Sep 2008 21:16:01 -0000 @@ -44,7 +44,7 @@ if (syntheticWriteAccessor == null) { codeStream.putstatic(fieldBinding); } else { - codeStream.invokestatic(syntheticWriteAccessor); + codeStream.invokestatic(syntheticWriteAccessor, null /* default declaringClass */); } } else { // Stack: [owner][new field value] ---> [new field value][owner][new field value] if (valueRequired) { @@ -57,7 +57,7 @@ if (syntheticWriteAccessor == null) { codeStream.putfield(fieldBinding); } else { - codeStream.invokestatic(syntheticWriteAccessor); + codeStream.invokestatic(syntheticWriteAccessor, null /* default declaringClass */); } } codeStream.recordPositionsFrom(pc, this.sourceStart); 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.109 diff -u -r1.109 SingleNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 12 Sep 2008 13:28:53 -0000 1.109 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java 15 Sep 2008 21:16:05 -0000 @@ -377,7 +377,7 @@ if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { codeStream.getstatic(fieldBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } else { if (!valueRequired @@ -399,7 +399,7 @@ if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { codeStream.getfield(fieldBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } break; @@ -474,7 +474,7 @@ if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { codeStream.getstatic(fieldBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } else { if ((this.bits & ASTNode.DepthMASK) != 0) { @@ -488,7 +488,7 @@ if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { codeStream.getfield(fieldBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } break; @@ -587,7 +587,7 @@ if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { codeStream.getstatic(fieldBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } else { if ((this.bits & ASTNode.DepthMASK) != 0) { @@ -601,7 +601,7 @@ if ((this.syntheticAccessors == null) || (this.syntheticAccessors[SingleNameReference.READ] == null)) { codeStream.getfield(fieldBinding); } else { - codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ]); + codeStream.invokestatic(this.syntheticAccessors[SingleNameReference.READ], null /* default declaringClass */); } } TypeBinding operandType; Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java,v retrieving revision 1.89 diff -u -r1.89 QualifiedAllocationExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java 27 Jun 2008 16:03:56 -0000 1.89 +++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java 15 Sep 2008 21:15:52 -0000 @@ -138,7 +138,7 @@ // invoke constructor if (this.syntheticAccessor == null) { - codeStream.invokespecial(this.codegenBinding); + codeStream.invokespecial(this.codegenBinding, null /* default declaringClass */); } else { // synthetic accessor got some extra arguments appended to its signature, which need values for (int i = 0, @@ -147,7 +147,7 @@ i++) { codeStream.aconst_null(); } - codeStream.invokespecial(this.syntheticAccessor); + codeStream.invokespecial(this.syntheticAccessor, null /* default declaringClass */); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); Index: compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java,v retrieving revision 1.73 diff -u -r1.73 SwitchStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java 27 Jun 2008 16:03:54 -0000 1.73 +++ compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java 15 Sep 2008 21:16:09 -0000 @@ -156,7 +156,7 @@ if (resolvedType.isEnum()) { if (needSwitch) { // go through the translation table - codeStream.invokestatic(this.synthetic); + codeStream.invokestatic(this.synthetic, null /* default declaringClass */); this.expression.generateCode(currentScope, codeStream, true); // get enum constant ordinal() codeStream.invokeEnumOrdinal(resolvedType.constantPoolName()); Index: compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java,v retrieving revision 1.74 diff -u -r1.74 AllocationExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java 27 Jun 2008 16:03:55 -0000 1.74 +++ compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java 15 Sep 2008 21:15:41 -0000 @@ -115,7 +115,7 @@ } // invoke constructor if (this.syntheticAccessor == null) { - codeStream.invokespecial(this.codegenBinding); + codeStream.invokespecial(this.codegenBinding, null /* default declaringClass */); } else { // synthetic accessor got some extra arguments appended to its signature, which need values for (int i = 0, @@ -124,7 +124,7 @@ i++) { codeStream.aconst_null(); } - codeStream.invokespecial(this.syntheticAccessor); + codeStream.invokespecial(this.syntheticAccessor, null /* default declaringClass */); } if (valueRequired) { codeStream.generateImplicitConversion(this.implicitConversion); Index: compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java,v retrieving revision 1.51 diff -u -r1.51 ForeachStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 28 Aug 2008 18:58:23 -0000 1.51 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java 15 Sep 2008 21:15:48 -0000 @@ -12,8 +12,8 @@ import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.codegen.BranchLabel; +import org.eclipse.jdt.internal.compiler.codegen.CodeStream; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext; @@ -27,6 +27,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; public class ForeachStatement extends Statement { @@ -63,6 +64,8 @@ int postCollectionInitStateIndex = -1; int mergedInitStateIndex = -1; + private static MethodBinding ITERATOR_METHOD; + public ForeachStatement( LocalDeclaration elementVariable, int start) { @@ -212,18 +215,10 @@ case GENERIC_ITERABLE : this.collection.generateCode(this.scope, codeStream, true); // declaringClass.iterator(); - MethodBinding iteratorMethodBinding = - new MethodBinding( - ClassFileConstants.AccPublic, - "iterator".toCharArray(),//$NON-NLS-1$ - this.scope.getJavaUtilIterator(), - Binding.NO_PARAMETERS, - Binding.NO_EXCEPTIONS, - (ReferenceBinding) this.iteratorReceiverType.erasure()); if (this.iteratorReceiverType.isInterface()) { - codeStream.invokeinterface(iteratorMethodBinding); + codeStream.invokeinterface(getIteratorMethod(), this.iteratorReceiverType); } else { - codeStream.invokevirtual(iteratorMethodBinding); + codeStream.invokevirtual(getIteratorMethod(), this.iteratorReceiverType); } codeStream.store(this.indexVariable, false); codeStream.addVariable(this.indexVariable); @@ -367,6 +362,19 @@ this.breakLabel.place(); codeStream.recordPositionsFrom(pc, this.sourceStart); } + private MethodBinding getIteratorMethod() { + if (ITERATOR_METHOD == null) { + ITERATOR_METHOD = new MethodBinding( + ClassFileConstants.AccPublic, + TypeConstants.ITERATOR, + this.scope.getJavaUtilIterator(), + Binding.NO_PARAMETERS, + Binding.NO_EXCEPTIONS, + null); + + } + return ITERATOR_METHOD; + } public StringBuffer printStatement(int indent, StringBuffer output) { 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.132 diff -u -r1.132 MessageSend.java --- compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 3 Sep 2008 12:01:53 -0000 1.132 +++ compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java 15 Sep 2008 21:15:52 -0000 @@ -34,7 +34,6 @@ import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; -import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; @@ -96,12 +95,10 @@ ? compileTimeType // unboxing: checkcast before conversion : runtimeTimeType; this.valueCast = originalType.genericCast(targetType); - } else if (this.actualReceiverType.isArrayType() - && runtimeTimeType.id != TypeIds.T_JavaLangObject - && this.binding.parameters == Binding.NO_PARAMETERS - && scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5 - && CharOperation.equals(this.binding.selector, TypeConstants.CLONE)) { - // from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast + } else if (this.binding == scope.environment().arrayClone + && runtimeTimeType.id != TypeIds.T_JavaLangObject + && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { + // from 1.5 source level on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast this.valueCast = runtimeTimeType; } if (this.valueCast instanceof ReferenceBinding) { @@ -148,23 +145,23 @@ } // generate arguments generateArguments(this.binding, this.arguments, currentScope, codeStream); + // actual message invocation if (this.syntheticAccessor == null){ + TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope); if (isStatic){ - codeStream.invokestatic(this.codegenBinding); + codeStream.invokestatic(this.codegenBinding, constantPoolDeclaringClass); + } else if( (this.receiver.isSuper()) || this.codegenBinding.isPrivate()){ + codeStream.invokespecial(this.codegenBinding, constantPoolDeclaringClass); } else { - if( (this.receiver.isSuper()) || this.codegenBinding.isPrivate()){ - codeStream.invokespecial(this.codegenBinding); + if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type + codeStream.invokeinterface(this.codegenBinding, constantPoolDeclaringClass); } else { - if (this.codegenBinding.declaringClass.isInterface()) { // interface or annotation type - codeStream.invokeinterface(this.codegenBinding); - } else { - codeStream.invokevirtual(this.codegenBinding); - } + codeStream.invokevirtual(this.codegenBinding, constantPoolDeclaringClass); } } } else { - codeStream.invokestatic(this.syntheticAccessor); + codeStream.invokestatic(this.syntheticAccessor, null /* default declaringClass */); } // required cast must occur even if no value is required if (this.valueCast != null) codeStream.checkcast(this.valueCast); @@ -188,7 +185,6 @@ } codeStream.recordPositionsFrom(pc, (int)(this.nameSourcePosition >>> 32)); // highlight selector } - /** * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments() */ @@ -196,6 +192,34 @@ return this.genericTypeArguments; } +protected TypeBinding getConstantPoolDeclaringClass(BlockScope currentScope) { + // constantpool declaringClass + TypeBinding constantPoolDeclaringClass = this.codegenBinding.declaringClass; + // Post 1.4.0 target, array clone() invocations are qualified with array type + // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding) + if (this.codegenBinding == currentScope.environment().arrayClone) { + CompilerOptions options = currentScope.compilerOptions(); + if (options.sourceLevel > ClassFileConstants.JDK1_4 ) { + constantPoolDeclaringClass = this.actualReceiverType.erasure(); + } + } else { + // 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, method's declaring class is touched if any different from receiver type + // and not from Object or implicit static method call. + if (constantPoolDeclaringClass != this.actualReceiverType && this.receiverGenericCast == null && !this.actualReceiverType.isArrayType()) { + CompilerOptions options = currentScope.compilerOptions(); + if ((options.targetJDK >= ClassFileConstants.JDK1_2 + && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic())) + && this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods + || !this.binding.declaringClass.canBeSeenBy(currentScope)) { + constantPoolDeclaringClass = this.actualReceiverType.erasure(); + } + } + } + return constantPoolDeclaringClass; +} + public boolean isSuperAccess() { return this.receiver.isSuper(); } @@ -239,26 +263,6 @@ return; } } - - // 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, method's declaring class is touched if any different from receiver type - // and not from Object or implicit static method call. - if (this.binding.declaringClass != this.actualReceiverType - && this.receiverGenericCast == null - && !this.actualReceiverType.isArrayType()) { - CompilerOptions options = currentScope.compilerOptions(); - if ((options.targetJDK >= ClassFileConstants.JDK1_2 - && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic())) - && this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods - || !this.binding.declaringClass.canBeSeenBy(currentScope)) { - - this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding( - this.codegenBinding, (ReferenceBinding) this.actualReceiverType.erasure()); - } - // Post 1.4.0 target, array clone() invocations are qualified with array type - // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding) - } } public int nullStatus(FlowInfo flowInfo) { return FlowInfo.UNKNOWN; @@ -507,11 +511,8 @@ if (isMethodUseDeprecated(this.binding, scope, true)) scope.problemReporter().deprecatedMethod(this.binding, this); - // from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object) - if (this.actualReceiverType.isArrayType() - && this.binding.parameters == Binding.NO_PARAMETERS - && compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5 - && CharOperation.equals(this.binding.selector, TypeConstants.CLONE)) { + // from 1.5 source level on, array#clone() returns the array type (but binding still shows Object) + if (this.binding == scope.environment().arrayClone && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) { this.resolvedType = this.actualReceiverType; } else { TypeBinding returnType = this.binding.returnType; Index: compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java,v retrieving revision 1.130 diff -u -r1.130 QualifiedNameReference.java --- compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 12 Sep 2008 13:28:53 -0000 1.130 +++ compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java 15 Sep 2008 21:16:01 -0000 @@ -401,7 +401,7 @@ codeStream.getfield(lastFieldBinding); } } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } if (requiredGenericCast != null) codeStream.checkcast(requiredGenericCast); if (valueRequired) { @@ -452,14 +452,14 @@ if (accessor == null) { codeStream.getstatic(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } } else { codeStream.dup(); if (accessor == null) { codeStream.getfield(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } } // the last field access is a write access @@ -501,14 +501,14 @@ if (accessor == null) { codeStream.getstatic(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } } else { codeStream.dup(); if (accessor == null) { codeStream.getfield(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } } TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length); @@ -628,7 +628,7 @@ codeStream.getfield(lastFieldBinding); } } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } if (lastGenericCast != null) codeStream.checkcast(lastGenericCast); if (!needValue) codeStream.pop(); @@ -641,7 +641,7 @@ if (accessor == null) { codeStream.getstatic(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } codeStream.pop(); } Index: compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java,v retrieving revision 1.65 diff -u -r1.65 ExplicitConstructorCall.java --- compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java 27 Jun 2008 16:03:55 -0000 1.65 +++ compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java 15 Sep 2008 21:15:44 -0000 @@ -148,9 +148,9 @@ i++) { codeStream.aconst_null(); } - codeStream.invokespecial(this.syntheticAccessor); + codeStream.invokespecial(this.syntheticAccessor, null /* default declaringClass */); } else { - codeStream.invokespecial(this.codegenBinding); + codeStream.invokespecial(this.codegenBinding, null /* default declaringClass */); } codeStream.recordPositionsFrom(pc, this.sourceStart); } finally { Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java,v retrieving revision 1.33 diff -u -r1.33 CodeSnippetReturnStatement.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java 27 Jun 2008 16:04:06 -0000 1.33 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java 15 Sep 2008 21:17:26 -0000 @@ -83,7 +83,7 @@ } // generate the invoke virtual to "setResult(Object,Class)" - codeStream.invokevirtual(this.setResultMethod); + codeStream.invokevirtual(this.setResultMethod, null /* default declaringClass */); } /** * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments() Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java,v retrieving revision 1.56 diff -u -r1.56 CodeSnippetMessageSend.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java 27 Jun 2008 16:04:06 -0000 1.56 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java 15 Sep 2008 21:17:22 -0000 @@ -32,7 +32,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; -public class CodeSnippetMessageSend extends MessageSend implements ProblemReasons, EvaluationConstants { +public class CodeSnippetMessageSend extends MessageSend { EvaluationContext evaluationContext; FieldBinding delegateThis; /** @@ -78,17 +78,16 @@ // generate arguments generateArguments(this.binding, this.arguments, currentScope, codeStream); // actual message invocation + TypeBinding constantPoolDeclaringClass = getConstantPoolDeclaringClass(currentScope); if (isStatic) { - codeStream.invokestatic(this.codegenBinding); + codeStream.invokestatic(this.codegenBinding, constantPoolDeclaringClass); + } else if( (this.receiver.isSuper()) || this.codegenBinding.isPrivate()){ + codeStream.invokespecial(this.codegenBinding, constantPoolDeclaringClass); } else { - if (this.receiver.isSuper()) { - codeStream.invokespecial(this.codegenBinding); + if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type + codeStream.invokeinterface(this.codegenBinding, constantPoolDeclaringClass); } else { - if (this.codegenBinding.declaringClass.isInterface()) { - codeStream.invokeinterface(this.codegenBinding); - } else { - codeStream.invokevirtual(this.codegenBinding); - } + codeStream.invokevirtual(this.codegenBinding, constantPoolDeclaringClass); } } } else { @@ -273,9 +272,9 @@ : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); if (!this.binding.isValidBinding()) { if (this.binding instanceof ProblemMethodBinding - && ((ProblemMethodBinding) this.binding).problemId() == NotVisible) { + && ((ProblemMethodBinding) this.binding).problemId() == ProblemReasons.NotVisible) { if (this.evaluationContext.declaringTypeName != null) { - this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this); + this.delegateThis = scope.getField(scope.enclosingSourceType(), EvaluationConstants.DELEGATE_THIS, this); if (this.delegateThis == null){ // if not found then internal error, field should have been found this.constant = Constant.NotAConstant; scope.problemReporter().invalidMethod(this, this.binding); Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java,v retrieving revision 1.38 diff -u -r1.38 CodeSnippetAllocationExpression.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java 27 Jun 2008 16:04:06 -0000 1.38 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java 15 Sep 2008 21:17:18 -0000 @@ -73,7 +73,7 @@ this); } // invoke constructor - codeStream.invokespecial(this.codegenBinding); + codeStream.invokespecial(this.codegenBinding, null /* default declaringClass */); } else { // private emulation using reflect codeStream.generateEmulationForConstructor(currentScope, this.codegenBinding); Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java,v retrieving revision 1.56 diff -u -r1.56 CodeSnippetQualifiedNameReference.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java 27 Jun 2008 16:04:07 -0000 1.56 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java 15 Sep 2008 21:17:26 -0000 @@ -222,14 +222,14 @@ if (accessor == null) { codeStream.getstatic(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } } else { codeStream.dup(); if (accessor == null) { codeStream.getfield(lastFieldBinding); } else { - codeStream.invokestatic(accessor); + codeStream.invokestatic(accessor, null /* default declaringClass */); } } Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java,v retrieving revision 1.52 diff -u -r1.52 CodeSnippetScope.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java 27 Jun 2008 16:04:07 -0000 1.52 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java 15 Sep 2008 21:17:27 -0000 @@ -271,7 +271,7 @@ if (!((ReferenceBinding)leafType).canBeSeenBy(this)) { return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ProblemReasons.ReceiverTypeNotVisible); } - if (CharOperation.equals(fieldName, LENGTH)) + if (CharOperation.equals(fieldName, TypeConstants.LENGTH)) return ArrayBinding.ArrayLength; return null; } @@ -371,8 +371,8 @@ MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes, null); if (methodBinding != null) { // handle the method clone() specially... cannot be protected or throw exceptions - if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, CLONE)) - return new MethodBinding((methodBinding.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic, CLONE, methodBinding.returnType, argumentTypes, null, object); + if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, TypeConstants.CLONE)) + return new MethodBinding((methodBinding.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic, TypeConstants.CLONE, methodBinding.returnType, argumentTypes, null, object); if (canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this)) return methodBinding; } #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/ArrayTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ArrayTest.java,v retrieving revision 1.25 diff -u -r1.25 ArrayTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/ArrayTest.java 27 Jun 2008 16:04:45 -0000 1.25 +++ src/org/eclipse/jdt/core/tests/compiler/regression/ArrayTest.java 15 Sep 2008 21:17:39 -0000 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.compiler.regression; import java.io.File; +import java.util.Map; import junit.framework.Test; @@ -393,4 +394,154 @@ "argument cannot be resolved\n" + "----------\n"); } +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=247307 +// Check return type of array#clone() +public void test014() throws Exception { + Map optionsMap = getCompilerOptions(); + CompilerOptions options = new CompilerOptions(optionsMap); + if (options.complianceLevel > ClassFileConstants.JDK1_4) { + // check that #clone() return type is changed ONLY from -source 1.5 only (independant from compliance level) + optionsMap.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4); + } + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(long[] longs) throws Exception {\n" + + " long[] other = longs.clone();\n" + + " }\n" + + "}\n", + }, + "----------\n" + + "1. ERROR in X.java (at line 3)\n" + + " long[] other = longs.clone();\n" + + " ^^^^^^^^^^^^^\n" + + "Type mismatch: cannot convert from Object to long[]\n" + + "----------\n", + null, + true, + optionsMap); +} +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=247307 - variation +//Check return type of array#clone() +public void test015() throws Exception { + if ( new CompilerOptions(getCompilerOptions()).sourceLevel < ClassFileConstants.JDK1_5) { + return; + } + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(long[] longs) throws Exception {\n" + + " long[] other = longs.clone();\n" + + " }\n" + + "}\n", + }, + ""); +} +//https:bugs.eclipse.org/bugs/show_bug.cgi?id=247307 - variation +//Check constant pool declaring class of array#clone() +public void test016() throws Exception { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(long[] longs) throws Exception {\n" + + " Object other = longs.clone();\n" + + " }\n" + + "}\n", + }, + ""); + ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); + byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator +"X.class")); + String actualOutput = + disassembler.disassemble( + classFileBytes, + "\n", + ClassFileBytesDisassembler.DETAILED); + + String expectedOutput = new CompilerOptions(getCompilerOptions()).sourceLevel <= ClassFileConstants.JDK1_4 + ? " // Method descriptor #15 ([J)V\n" + + " // Stack: 1, Locals: 3\n" + + " void foo(long[] longs) throws java.lang.Exception;\n" + + " 0 aload_1 [longs]\n" + + " 1 invokevirtual java.lang.Object.clone() : java.lang.Object [19]\n" + + " 4 astore_2 [other]\n" + + " 5 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 3]\n" + + " [pc: 5, line: 4]\n" + : " // Method descriptor #15 ([J)V\n" + + " // Stack: 1, Locals: 3\n" + + " void foo(long[] longs) throws java.lang.Exception;\n" + + " 0 aload_1 [longs]\n" + + " 1 invokevirtual long[].clone() : java.lang.Object [19]\n" + + " 4 astore_2 [other]\n" + + " 5 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 3]\n" + + " [pc: 5, line: 4]\n"; + + int index = actualOutput.indexOf(expectedOutput); + if (index == -1 || expectedOutput.length() == 0) { + System.out.println(Util.displayString(actualOutput, 3)); + } + if (index == -1) { + assertEquals("unexpected bytecode sequence", expectedOutput, actualOutput); + } + return; +} + +//https://bugs.eclipse.org/bugs/show_bug.cgi?id=247307 - variation +//Check constant pool declaring class of array#clone() +public void test017() throws Exception { + Map optionsMap = getCompilerOptions(); + CompilerOptions options = new CompilerOptions(optionsMap); + if (options.complianceLevel > ClassFileConstants.JDK1_4) { + // check that #clone() return type is changed ONLY from -source 1.5 only (independant from compliance level) + optionsMap.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4); + } + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(long[] longs) throws Exception {\n" + + " Object other = longs.clone();\n" + + " }\n" + + "}\n", + }, + "", + null, + true, + null, + optionsMap, + null); + ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); + byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(new File(OUTPUT_DIR + File.separator +"X.class")); + String actualOutput = + disassembler.disassemble( + classFileBytes, + "\n", + ClassFileBytesDisassembler.DETAILED); + + String expectedOutput = + " // Method descriptor #15 ([J)V\n" + + " // Stack: 1, Locals: 3\n" + + " void foo(long[] longs) throws java.lang.Exception;\n" + + " 0 aload_1 [longs]\n" + + " 1 invokevirtual java.lang.Object.clone() : java.lang.Object [19]\n" + + " 4 astore_2 [other]\n" + + " 5 return\n" + + " Line numbers:\n" + + " [pc: 0, line: 3]\n" + + " [pc: 5, line: 4]\n"; + + int index = actualOutput.indexOf(expectedOutput); + if (index == -1 || expectedOutput.length() == 0) { + System.out.println(Util.displayString(actualOutput, 3)); + } + if (index == -1) { + assertEquals("unexpected bytecode sequence", expectedOutput, actualOutput); + } +} } Index: src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java,v retrieving revision 1.101 diff -u -r1.101 Compliance_1_4.java --- src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java 27 Jun 2008 16:04:44 -0000 1.101 +++ src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java 15 Sep 2008 21:17:48 -0000 @@ -1423,8 +1423,9 @@ "\n", ClassFileBytesDisassembler.DETAILED); - String expectedOutput = - " 1 invokevirtual java.lang.String[].clone() : java.lang.Object [16]\n"; + String expectedOutput = new CompilerOptions(getCompilerOptions()).sourceLevel <= ClassFileConstants.JDK1_4 + ? " 1 invokevirtual java.lang.Object.clone() : java.lang.Object [16]\n" + : " 1 invokevirtual java.lang.String[].clone() : java.lang.Object [16]\n"; int index = actualOutput.indexOf(expectedOutput); if (index == -1 || expectedOutput.length() == 0) {