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

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java (-2 / +19 lines)
Lines 286-294 Link Here
286
			if (this.resolvedType instanceof ReferenceBinding) {
286
			if (this.resolvedType instanceof ReferenceBinding) {
287
				// record a best guess, for clients who need hint about possible contructor match
287
				// record a best guess, for clients who need hint about possible contructor match
288
				TypeBinding[] pseudoArgs = new TypeBinding[length];
288
				TypeBinding[] pseudoArgs = new TypeBinding[length];
289
				for (int i = length; --i >= 0;)
289
				for (int i = length; --i >= 0;) {
290
					pseudoArgs[i] = argumentTypes[i] == null ? this.resolvedType : argumentTypes[i]; // replace args with errors with receiver
290
					pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
291
				}
291
				this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this);
292
				this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this);
293
				if (this.binding != null && !this.binding.isValidBinding()) {
294
					MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
295
					// record the closest match, for clients who may still need hint about possible method match
296
					if (closestMatch != null) {
297
						if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
298
							// shouldn't return generic method outside its context, rather convert it to raw method (175409)
299
							closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
300
						}
301
						this.binding = closestMatch;
302
						MethodBinding closestMatchOriginal = closestMatch.original();
303
						if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
304
							// ignore cases where method is used from within inside itself (e.g. direct recursions)
305
							closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
306
						}
307
					}
308
				}
292
			}
309
			}
293
			return this.resolvedType;
310
			return this.resolvedType;
294
		}
311
		}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java (-1 / +33 lines)
Lines 18-30 Link Here
18
import org.eclipse.jdt.internal.compiler.impl.Constant;
18
import org.eclipse.jdt.internal.compiler.impl.Constant;
19
import org.eclipse.jdt.internal.compiler.lookup.Binding;
19
import org.eclipse.jdt.internal.compiler.lookup.Binding;
20
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
20
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
21
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
21
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
22
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
24
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
23
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
25
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
24
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
27
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
25
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
26
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
29
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
27
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
30
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
28
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
32
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
29
33
30
/**
34
/**
Lines 311-317 Link Here
311
			}
315
			}
312
		}
316
		}
313
		// limit of fault-tolerance
317
		// limit of fault-tolerance
314
		if (hasError) return this.resolvedType = receiverType;
318
		if (hasError) {
319
			if (receiverType instanceof ReferenceBinding) {
320
				// record a best guess, for clients who need hint about possible contructor match
321
				int length = this.arguments  == null ? 0 : this.arguments.length;
322
				TypeBinding[] pseudoArgs = new TypeBinding[length];
323
				for (int i = length; --i >= 0;) {
324
					pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
325
				}
326
				this.binding = scope.findMethod((ReferenceBinding) receiverType, TypeConstants.INIT, pseudoArgs, this);
327
				if (this.binding != null && !this.binding.isValidBinding()) {
328
					MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
329
					// record the closest match, for clients who may still need hint about possible method match
330
					if (closestMatch != null) {
331
						if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
332
							// shouldn't return generic method outside its context, rather convert it to raw method (175409)
333
							closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
334
						}
335
						this.binding = closestMatch;
336
						MethodBinding closestMatchOriginal = closestMatch.original();
337
						if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
338
							// ignore cases where method is used from within inside itself (e.g. direct recursions)
339
							closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
340
						}
341
					}
342
				}
343
				
344
			}
345
			return this.resolvedType = receiverType;
346
		}
315
		if (this.anonymousType == null) {
347
		if (this.anonymousType == null) {
316
			// qualified allocation with no anonymous type
348
			// qualified allocation with no anonymous type
317
			if (!receiverType.canBeInstantiated()) {
349
			if (!receiverType.canBeInstantiated()) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java (-2 / +19 lines)
Lines 340-348 Link Here
340
				if (argHasError) {
340
				if (argHasError) {
341
					// record a best guess, for clients who need hint about possible contructor match
341
					// record a best guess, for clients who need hint about possible contructor match
342
					TypeBinding[] pseudoArgs = new TypeBinding[length];
342
					TypeBinding[] pseudoArgs = new TypeBinding[length];
343
					for (int i = length; --i >= 0;)
343
					for (int i = length; --i >= 0;) {
344
						pseudoArgs[i] = argumentTypes[i] == null ? receiverType : argumentTypes[i]; // replace args with errors with receiver
344
						pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
345
					}
345
					this.binding = scope.findMethod(receiverType, TypeConstants.INIT, pseudoArgs, this);
346
					this.binding = scope.findMethod(receiverType, TypeConstants.INIT, pseudoArgs, this);
347
					if (this.binding != null && !this.binding.isValidBinding()) {
348
						MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
349
						// record the closest match, for clients who may still need hint about possible method match
350
						if (closestMatch != null) {
351
							if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
352
								// shouldn't return generic method outside its context, rather convert it to raw method (175409)
353
								closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
354
							}
355
							this.binding = closestMatch;
356
							MethodBinding closestMatchOriginal = closestMatch.original();
357
							if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
358
								// ignore cases where method is used from within inside itself (e.g. direct recursions)
359
								closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
360
							}
361
						}
362
					}
346
					return;
363
					return;
347
				}
364
				}
348
			} else if (receiverType.erasure().id == T_JavaLangEnum) {
365
			} else if (receiverType.erasure().id == T_JavaLangEnum) {
(-)compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java (-98 / +119 lines)
Lines 13-25 Link Here
13
13
14
import org.eclipse.jdt.core.compiler.CharOperation;
14
import org.eclipse.jdt.core.compiler.CharOperation;
15
import org.eclipse.jdt.internal.compiler.ASTVisitor;
15
import org.eclipse.jdt.internal.compiler.ASTVisitor;
16
import org.eclipse.jdt.internal.compiler.flow.*;
16
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
18
import org.eclipse.jdt.internal.compiler.flow.FlowContext;
19
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
17
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
20
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
18
import org.eclipse.jdt.internal.compiler.impl.Constant;
21
import org.eclipse.jdt.internal.compiler.impl.Constant;
19
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
22
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
20
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
23
import org.eclipse.jdt.internal.compiler.lookup.Binding;
21
import org.eclipse.jdt.internal.compiler.codegen.*;
24
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
22
import org.eclipse.jdt.internal.compiler.lookup.*;
25
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
26
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
27
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
28
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
29
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
30
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
31
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
32
import org.eclipse.jdt.internal.compiler.lookup.Scope;
33
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
34
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
35
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
36
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
37
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
23
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
38
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
24
39
25
public class MessageSend extends Expression implements InvocationSite {
40
public class MessageSend extends Expression implements InvocationSite {
Lines 42-61 Link Here
42
	
57
	
43
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
58
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
44
59
45
	boolean nonStatic = !binding.isStatic();
60
	boolean nonStatic = !this.binding.isStatic();
46
	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
61
	flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits();
47
	if (nonStatic) {
62
	if (nonStatic) {
48
		receiver.checkNPE(currentScope, flowContext, flowInfo);
63
		this.receiver.checkNPE(currentScope, flowContext, flowInfo);
49
	}
64
	}
50
65
51
	if (arguments != null) {
66
	if (this.arguments != null) {
52
		int length = arguments.length;
67
		int length = this.arguments.length;
53
		for (int i = 0; i < length; i++) {
68
		for (int i = 0; i < length; i++) {
54
			flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
69
			flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
55
		}
70
		}
56
	}
71
	}
57
	ReferenceBinding[] thrownExceptions;
72
	ReferenceBinding[] thrownExceptions;
58
	if ((thrownExceptions = binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
73
	if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
59
		// must verify that exceptions potentially thrown by this expression are caught in the method
74
		// must verify that exceptions potentially thrown by this expression are caught in the method
60
		flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo.copy(), currentScope);
75
		flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo.copy(), currentScope);
61
		// TODO (maxime) the copy above is needed because of a side effect into 
76
		// TODO (maxime) the copy above is needed because of a side effect into 
Lines 78-94 Link Here
78
	    // extra cast needed if method return type is type variable
93
	    // extra cast needed if method return type is type variable
79
		if (originalBinding != this.binding 
94
		if (originalBinding != this.binding 
80
				&& originalType != this.binding.returnType
95
				&& originalType != this.binding.returnType
81
				&& runtimeTimeType.id != T_JavaLangObject
96
				&& runtimeTimeType.id != TypeIds.T_JavaLangObject
82
				&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) {
97
				&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) {
83
	    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
98
	    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
84
	    		? compileTimeType  // unboxing: checkcast before conversion
99
	    		? compileTimeType  // unboxing: checkcast before conversion
85
	    		: runtimeTimeType;
100
	    		: runtimeTimeType;
86
	        this.valueCast = originalType.genericCast(targetType); 
101
	        this.valueCast = originalType.genericCast(targetType); 
87
		} 	else if (this.actualReceiverType.isArrayType() 
102
		} 	else if (this.actualReceiverType.isArrayType() 
88
						&& runtimeTimeType.id != T_JavaLangObject
103
						&& runtimeTimeType.id != TypeIds.T_JavaLangObject
89
						&& this.binding.parameters == Binding.NO_PARAMETERS 
104
						&& this.binding.parameters == Binding.NO_PARAMETERS 
90
						&& scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5 
105
						&& scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5 
91
						&& CharOperation.equals(this.binding.selector, CLONE)) {
106
						&& CharOperation.equals(this.binding.selector, TypeConstants.CLONE)) {
92
					// from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast
107
					// from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast
93
			this.valueCast = runtimeTimeType;			
108
			this.valueCast = runtimeTimeType;			
94
		}
109
		}
Lines 110-137 Link Here
110
	// generate receiver/enclosing instance access
125
	// generate receiver/enclosing instance access
111
	boolean isStatic = this.codegenBinding.isStatic();
126
	boolean isStatic = this.codegenBinding.isStatic();
112
	if (isStatic) {
127
	if (isStatic) {
113
		receiver.generateCode(currentScope, codeStream, false);
128
		this.receiver.generateCode(currentScope, codeStream, false);
114
		codeStream.recordPositionsFrom(pc, this.sourceStart);
129
		codeStream.recordPositionsFrom(pc, this.sourceStart);
115
	} else if ((bits & DepthMASK) != 0 && receiver.isImplicitThis()) { // outer access ?
130
	} else if ((this.bits & ASTNode.DepthMASK) != 0 && this.receiver.isImplicitThis()) { // outer access ?
116
		// outer method can be reached through emulation if implicit access
131
		// outer method can be reached through emulation if implicit access
117
		ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);		
132
		ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);		
118
		Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
133
		Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
119
		codeStream.generateOuterAccess(path, this, targetType, currentScope);
134
		codeStream.generateOuterAccess(path, this, targetType, currentScope);
120
	} else {
135
	} else {
121
		receiver.generateCode(currentScope, codeStream, true);
136
		this.receiver.generateCode(currentScope, codeStream, true);
122
		if (this.receiverGenericCast != null) 
137
		if (this.receiverGenericCast != null) 
123
			codeStream.checkcast(this.receiverGenericCast);
138
			codeStream.checkcast(this.receiverGenericCast);
124
		codeStream.recordPositionsFrom(pc, this.sourceStart);
139
		codeStream.recordPositionsFrom(pc, this.sourceStart);
125
		
140
		
126
	}
141
	}
127
	// generate arguments
142
	// generate arguments
128
	generateArguments(binding, arguments, currentScope, codeStream);
143
	generateArguments(this.binding, this.arguments, currentScope, codeStream);
129
	// actual message invocation
144
	// actual message invocation
130
	if (syntheticAccessor == null){
145
	if (this.syntheticAccessor == null){
131
		if (isStatic){
146
		if (isStatic){
132
			codeStream.invokestatic(this.codegenBinding);
147
			codeStream.invokestatic(this.codegenBinding);
133
		} else {
148
		} else {
134
			if( (receiver.isSuper()) || this.codegenBinding.isPrivate()){
149
			if( (this.receiver.isSuper()) || this.codegenBinding.isPrivate()){
135
				codeStream.invokespecial(this.codegenBinding);
150
				codeStream.invokespecial(this.codegenBinding);
136
			} else {
151
			} else {
137
				if (this.codegenBinding.declaringClass.isInterface()) { // interface or annotation type
152
				if (this.codegenBinding.declaringClass.isInterface()) { // interface or annotation type
Lines 142-158 Link Here
142
			}
157
			}
143
		}
158
		}
144
	} else {
159
	} else {
145
		codeStream.invokestatic(syntheticAccessor);
160
		codeStream.invokestatic(this.syntheticAccessor);
146
	}
161
	}
147
	// required cast must occur even if no value is required
162
	// required cast must occur even if no value is required
148
	if (this.valueCast != null) codeStream.checkcast(this.valueCast);
163
	if (this.valueCast != null) codeStream.checkcast(this.valueCast);
149
	if (valueRequired){
164
	if (valueRequired){
150
		// implicit conversion if necessary
165
		// implicit conversion if necessary
151
		codeStream.generateImplicitConversion(implicitConversion);
166
		codeStream.generateImplicitConversion(this.implicitConversion);
152
	} else {
167
	} else {
153
		boolean isUnboxing = (implicitConversion & TypeIds.UNBOXING) != 0;
168
		boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
154
		// conversion only generated if unboxing
169
		// conversion only generated if unboxing
155
		if (isUnboxing) codeStream.generateImplicitConversion(implicitConversion);
170
		if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
156
		switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.returnType.id) {
171
		switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.returnType.id) {
157
			case T_long :
172
			case T_long :
158
			case T_double :
173
			case T_double :
Lines 175-184 Link Here
175
}	
190
}	
176
191
177
public boolean isSuperAccess() {	
192
public boolean isSuperAccess() {	
178
	return receiver.isSuper();
193
	return this.receiver.isSuper();
179
}
194
}
180
public boolean isTypeAccess() {	
195
public boolean isTypeAccess() {	
181
	return receiver != null && receiver.isTypeReference();
196
	return this.receiver != null && this.receiver.isTypeReference();
182
}
197
}
183
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
198
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
184
199
Lines 191-218 Link Here
191
		// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)		
206
		// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)		
192
		if (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass){
207
		if (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass){
193
		
208
		
194
			syntheticAccessor = ((SourceTypeBinding)this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
209
			this.syntheticAccessor = ((SourceTypeBinding)this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess());
195
			currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
210
			currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
196
			return;
211
			return;
197
		}
212
		}
198
213
199
	} else if (receiver instanceof QualifiedSuperReference){ // qualified super
214
	} else if (this.receiver instanceof QualifiedSuperReference){ // qualified super
200
215
201
		// qualified super need emulation always
216
		// qualified super need emulation always
202
		SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)receiver).currentCompatibleType);
217
		SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)this.receiver).currentCompatibleType);
203
		syntheticAccessor = destinationType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
218
		this.syntheticAccessor = destinationType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
204
		currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
219
		currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
205
		return;
220
		return;
206
221
207
	} else if (binding.isProtected()){
222
	} else if (this.binding.isProtected()){
208
223
209
		SourceTypeBinding enclosingSourceType;
224
		SourceTypeBinding enclosingSourceType;
210
		if (((bits & DepthMASK) != 0) 
225
		if (((this.bits & ASTNode.DepthMASK) != 0) 
211
				&& this.codegenBinding.declaringClass.getPackage() 
226
				&& this.codegenBinding.declaringClass.getPackage() 
212
					!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){
227
					!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){
213
228
214
			SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
229
			SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
215
			syntheticAccessor = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
230
			this.syntheticAccessor = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isSuperAccess());
216
			currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
231
			currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this);
217
			return;
232
			return;
218
		}
233
		}
Lines 227-234 Link Here
227
			&& !this.actualReceiverType.isArrayType()) {
242
			&& !this.actualReceiverType.isArrayType()) {
228
		CompilerOptions options = currentScope.compilerOptions();
243
		CompilerOptions options = currentScope.compilerOptions();
229
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
244
		if ((options.targetJDK >= ClassFileConstants.JDK1_2
230
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(receiver.isImplicitThis() && this.codegenBinding.isStatic()))
245
				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic()))
231
				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object methods
246
				&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods
232
			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
247
			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
233
248
234
			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(
249
			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(
Lines 249-255 Link Here
249
	TypeBinding convertedType = this.resolvedType;
264
	TypeBinding convertedType = this.resolvedType;
250
	if (this.valueCast != null) 
265
	if (this.valueCast != null) 
251
		convertedType = this.valueCast;
266
		convertedType = this.valueCast;
252
	int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
267
	int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
253
	switch (runtimeType) {
268
	switch (runtimeType) {
254
		case T_boolean :
269
		case T_boolean :
255
			convertedType = TypeBinding.BOOLEAN;
270
			convertedType = TypeBinding.BOOLEAN;
Lines 277-283 Link Here
277
			break;
292
			break;
278
		default :
293
		default :
279
	}		
294
	}		
280
	if ((this.implicitConversion & BOXING) != 0) {
295
	if ((this.implicitConversion & TypeIds.BOXING) != 0) {
281
		convertedType = scope.environment().computeBoxingType(convertedType);
296
		convertedType = scope.environment().computeBoxingType(convertedType);
282
	}
297
	}
283
	return convertedType;
298
	return convertedType;
Lines 285-306 Link Here
285
	
300
	
286
public StringBuffer printExpression(int indent, StringBuffer output){
301
public StringBuffer printExpression(int indent, StringBuffer output){
287
	
302
	
288
	if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.');
303
	if (!this.receiver.isImplicitThis()) this.receiver.printExpression(0, output).append('.');
289
	if (this.typeArguments != null) {
304
	if (this.typeArguments != null) {
290
		output.append('<');
305
		output.append('<');
291
		int max = typeArguments.length - 1;
306
		int max = this.typeArguments.length - 1;
292
		for (int j = 0; j < max; j++) {
307
		for (int j = 0; j < max; j++) {
293
			typeArguments[j].print(0, output);
308
			this.typeArguments[j].print(0, output);
294
			output.append(", ");//$NON-NLS-1$
309
			output.append(", ");//$NON-NLS-1$
295
		}
310
		}
296
		typeArguments[max].print(0, output);
311
		this.typeArguments[max].print(0, output);
297
		output.append('>');
312
		output.append('>');
298
	}
313
	}
299
	output.append(selector).append('(') ;
314
	output.append(this.selector).append('(') ;
300
	if (arguments != null) {
315
	if (this.arguments != null) {
301
		for (int i = 0; i < arguments.length ; i ++) {	
316
		for (int i = 0; i < this.arguments.length ; i ++) {	
302
			if (i > 0) output.append(", "); //$NON-NLS-1$
317
			if (i > 0) output.append(", "); //$NON-NLS-1$
303
			arguments[i].printExpression(0, output);
318
			this.arguments[i].printExpression(0, output);
304
		}
319
		}
305
	}
320
	}
306
	return output.append(')');
321
	return output.append(')');
Lines 310-323 Link Here
310
	// Answer the signature return type
325
	// Answer the signature return type
311
	// Base type promotion
326
	// Base type promotion
312
327
313
	constant = Constant.NotAConstant;
328
	this.constant = Constant.NotAConstant;
314
	boolean receiverCast = false, argsContainCast = false; 
329
	boolean receiverCast = false, argsContainCast = false; 
315
	if (this.receiver instanceof CastExpression) {
330
	if (this.receiver instanceof CastExpression) {
316
		this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
331
		this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
317
		receiverCast = true;
332
		receiverCast = true;
318
	}
333
	}
319
	this.actualReceiverType = receiver.resolveType(scope); 
334
	this.actualReceiverType = this.receiver.resolveType(scope); 
320
	boolean receiverIsType = receiver instanceof NameReference && (((NameReference) receiver).bits & Binding.TYPE) != 0;
335
	boolean receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0;
321
	if (receiverCast && this.actualReceiverType != null) {
336
	if (receiverCast && this.actualReceiverType != null) {
322
		 // due to change of declaring class with receiver type, only identity cast should be notified
337
		 // due to change of declaring class with receiver type, only identity cast should be notified
323
		if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { 
338
		if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { 
Lines 344-357 Link Here
344
	}	
359
	}	
345
	// will check for null after args are resolved
360
	// will check for null after args are resolved
346
	TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
361
	TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
347
	if (arguments != null) {
362
	if (this.arguments != null) {
348
		boolean argHasError = false; // typeChecks all arguments 
363
		boolean argHasError = false; // typeChecks all arguments 
349
		int length = arguments.length;
364
		int length = this.arguments.length;
350
		argumentTypes = new TypeBinding[length];
365
		argumentTypes = new TypeBinding[length];
351
		for (int i = 0; i < length; i++){
366
		for (int i = 0; i < length; i++){
352
			Expression argument = arguments[i];
367
			Expression argument = this.arguments[i];
353
			if (argument instanceof CastExpression) {
368
			if (argument instanceof CastExpression) {
354
				argument.bits |= DisableUnnecessaryCastCheck; // will check later on
369
				argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
355
				argsContainCast = true;
370
				argsContainCast = true;
356
			}
371
			}
357
			if ((argumentTypes[i] = argument.resolveType(scope)) == null){
372
			if ((argumentTypes[i] = argument.resolveType(scope)) == null){
Lines 359-381 Link Here
359
			}
374
			}
360
		}
375
		}
361
		if (argHasError) {
376
		if (argHasError) {
362
			if (actualReceiverType instanceof ReferenceBinding) {
377
			if (this.actualReceiverType instanceof ReferenceBinding) {
363
				//  record a best guess, for clients who need hint about possible method match
378
				//  record a best guess, for clients who need hint about possible method match
364
				TypeBinding[] pseudoArgs = new TypeBinding[length];
379
				TypeBinding[] pseudoArgs = new TypeBinding[length];
365
				for (int i = length; --i >= 0;)
380
				for (int i = length; --i >= 0;)
366
					pseudoArgs[i] = argumentTypes[i] == null ? actualReceiverType : argumentTypes[i]; // replace args with errors with receiver
381
					pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
367
				this.binding = 
382
				this.binding = 
368
					receiver.isImplicitThis()
383
					this.receiver.isImplicitThis()
369
						? scope.getImplicitMethod(selector, pseudoArgs, this)
384
						? scope.getImplicitMethod(this.selector, pseudoArgs, this)
370
						: scope.findMethod((ReferenceBinding) actualReceiverType, selector, pseudoArgs, this);
385
						: scope.findMethod((ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this);
371
				if (binding != null && !binding.isValidBinding()) {
386
				if (this.binding != null && !this.binding.isValidBinding()) {
372
					MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
387
					MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
373
					// record the closest match, for clients who may still need hint about possible method match
388
					// record the closest match, for clients who may still need hint about possible method match
374
					if (closestMatch != null) {
389
					if (closestMatch != null) {
390
						if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
391
							// shouldn't return generic method outside its context, rather convert it to raw method (175409)
392
							closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
393
						}
375
						this.binding = closestMatch;
394
						this.binding = closestMatch;
376
						if ((closestMatch.isPrivate() || closestMatch.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatch)) {
395
						MethodBinding closestMatchOriginal = closestMatch.original();
396
						if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
377
							// ignore cases where method is used from within inside itself (e.g. direct recursions)
397
							// ignore cases where method is used from within inside itself (e.g. direct recursions)
378
							closestMatch.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
398
							closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
379
						}
399
						}
380
					}
400
					}
381
				}
401
				}
Lines 392-411 Link Here
392
		return null;
412
		return null;
393
	}
413
	}
394
	this.binding = 
414
	this.binding = 
395
		receiver.isImplicitThis()
415
		this.receiver.isImplicitThis()
396
			? scope.getImplicitMethod(selector, argumentTypes, this)
416
			? scope.getImplicitMethod(this.selector, argumentTypes, this)
397
			: scope.getMethod(this.actualReceiverType, selector, argumentTypes, this); 
417
			: scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); 
398
	if (!binding.isValidBinding()) {
418
	if (!this.binding.isValidBinding()) {
399
		if (binding.declaringClass == null) {
419
		if (this.binding.declaringClass == null) {
400
			if (this.actualReceiverType instanceof ReferenceBinding) {
420
			if (this.actualReceiverType instanceof ReferenceBinding) {
401
				binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
421
				this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
402
			} else { 
422
			} else { 
403
				scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
423
				scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
404
				return null;
424
				return null;
405
			}
425
			}
406
		}
426
		}
407
		scope.problemReporter().invalidMethod(this, binding);
427
		scope.problemReporter().invalidMethod(this, this.binding);
408
		MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
428
		MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
409
		switch (this.binding.problemId()) {
429
		switch (this.binding.problemId()) {
410
			case ProblemReasons.Ambiguous :
430
			case ProblemReasons.Ambiguous :
411
				break; // no resilience on ambiguous
431
				break; // no resilience on ambiguous
Lines 421-445 Link Here
421
		// record the closest match, for clients who may still need hint about possible method match
441
		// record the closest match, for clients who may still need hint about possible method match
422
		if (closestMatch != null) {
442
		if (closestMatch != null) {
423
			this.binding = closestMatch;
443
			this.binding = closestMatch;
424
			if ((closestMatch.isPrivate() || closestMatch.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatch)) {
444
			MethodBinding closestMatchOriginal = closestMatch.original();			
445
			if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) {
425
				// ignore cases where method is used from within inside itself (e.g. direct recursions)
446
				// ignore cases where method is used from within inside itself (e.g. direct recursions)
426
				closestMatch.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
447
				closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
427
			}
448
			}
428
		}
449
		}
429
		return this.resolvedType;
450
		return this.resolvedType;
430
	}
451
	}
431
	final CompilerOptions compilerOptions = scope.compilerOptions();
452
	final CompilerOptions compilerOptions = scope.compilerOptions();
432
	if (!binding.isStatic()) {
453
	if (!this.binding.isStatic()) {
433
		// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
454
		// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
434
		if (receiverIsType) {
455
		if (receiverIsType) {
435
			scope.problemReporter().mustUseAStaticMethod(this, binding);
456
			scope.problemReporter().mustUseAStaticMethod(this, this.binding);
436
			if (this.actualReceiverType.isRawType() 
457
			if (this.actualReceiverType.isRawType() 
437
					&& (this.receiver.bits & IgnoreRawTypeCheck) == 0 
458
					&& (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0 
438
					&& compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) {
459
					&& compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) {
439
				scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType);
460
				scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType);
440
			}
461
			}
441
		} else {
462
		} else {
442
			receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
463
			this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
443
			// compute generic cast if necessary
464
			// compute generic cast if necessary
444
			TypeBinding receiverErasure = this.actualReceiverType.erasure();
465
			TypeBinding receiverErasure = this.actualReceiverType.erasure();
445
			if (receiverErasure instanceof ReferenceBinding) {
466
			if (receiverErasure instanceof ReferenceBinding) {
Lines 450-486 Link Here
450
		}
471
		}
451
	} else {
472
	} else {
452
		// static message invoked through receiver? legal but unoptimal (optional warning).
473
		// static message invoked through receiver? legal but unoptimal (optional warning).
453
		if (!(receiver.isImplicitThis() || receiver.isSuper() || receiverIsType)) {
474
		if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) {
454
			scope.problemReporter().nonStaticAccessToStaticMethod(this, binding);
475
			scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding);
455
		}
476
		}
456
		if (!receiver.isImplicitThis() && binding.declaringClass != actualReceiverType) {
477
		if (!this.receiver.isImplicitThis() && this.binding.declaringClass != this.actualReceiverType) {
457
			scope.problemReporter().indirectAccessToStaticMethod(this, binding);
478
			scope.problemReporter().indirectAccessToStaticMethod(this, this.binding);
458
		}		
479
		}		
459
	}
480
	}
460
	checkInvocationArguments(scope, this.receiver, actualReceiverType, binding, this.arguments, argumentTypes, argsContainCast, this);
481
	checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this);
461
482
462
	//-------message send that are known to fail at compile time-----------
483
	//-------message send that are known to fail at compile time-----------
463
	if (binding.isAbstract()) {
484
	if (this.binding.isAbstract()) {
464
		if (receiver.isSuper()) {
485
		if (this.receiver.isSuper()) {
465
			scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, binding);
486
			scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding);
466
		}
487
		}
467
		// abstract private methods cannot occur nor abstract static............
488
		// abstract private methods cannot occur nor abstract static............
468
	}
489
	}
469
	if (isMethodUseDeprecated(binding, scope, true))
490
	if (isMethodUseDeprecated(this.binding, scope, true))
470
		scope.problemReporter().deprecatedMethod(binding, this);
491
		scope.problemReporter().deprecatedMethod(this.binding, this);
471
492
472
	// from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object)
493
	// from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object)
473
	if (actualReceiverType.isArrayType() 
494
	if (this.actualReceiverType.isArrayType() 
474
			&& this.binding.parameters == Binding.NO_PARAMETERS 
495
			&& this.binding.parameters == Binding.NO_PARAMETERS 
475
			&& compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5 
496
			&& compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5 
476
			&& CharOperation.equals(this.binding.selector, CLONE)) {
497
			&& CharOperation.equals(this.binding.selector, TypeConstants.CLONE)) {
477
		this.resolvedType = actualReceiverType;
498
		this.resolvedType = this.actualReceiverType;
478
	} else {
499
	} else {
479
		TypeBinding returnType = this.binding.returnType;
500
		TypeBinding returnType = this.binding.returnType;
480
		if (returnType != null) returnType = returnType.capture(scope, this.sourceEnd);
501
		if (returnType != null) returnType = returnType.capture(scope, this.sourceEnd);
481
		this.resolvedType = returnType;
502
		this.resolvedType = returnType;
482
	}
503
	}
483
	if (receiver.isSuper() && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) {
504
	if (this.receiver.isSuper() && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) {
484
		final ReferenceContext referenceContext = scope.methodScope().referenceContext;
505
		final ReferenceContext referenceContext = scope.methodScope().referenceContext;
485
		if (referenceContext instanceof AbstractMethodDeclaration) {
506
		if (referenceContext instanceof AbstractMethodDeclaration) {
486
			final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext;
507
			final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext;
Lines 500-508 Link Here
500
	this.actualReceiverType = receiverType;
521
	this.actualReceiverType = receiverType;
501
}
522
}
502
public void setDepth(int depth) {
523
public void setDepth(int depth) {
503
	bits &= ~DepthMASK; // flush previous depth if any
524
	this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any
504
	if (depth > 0) {
525
	if (depth > 0) {
505
		bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
526
		this.bits |= (depth & 0xFF) << ASTNode.DepthSHIFT; // encoded on 8 bits
506
	}
527
	}
507
}
528
}
508
529
Lines 518-533 Link Here
518
539
519
public void traverse(ASTVisitor visitor, BlockScope blockScope) {
540
public void traverse(ASTVisitor visitor, BlockScope blockScope) {
520
	if (visitor.visit(this, blockScope)) {
541
	if (visitor.visit(this, blockScope)) {
521
		receiver.traverse(visitor, blockScope);
542
		this.receiver.traverse(visitor, blockScope);
522
		if (this.typeArguments != null) {
543
		if (this.typeArguments != null) {
523
			for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
544
			for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
524
				this.typeArguments[i].traverse(visitor, blockScope);
545
				this.typeArguments[i].traverse(visitor, blockScope);
525
			}		
546
			}		
526
		}
547
		}
527
		if (arguments != null) {
548
		if (this.arguments != null) {
528
			int argumentsLength = arguments.length;
549
			int argumentsLength = this.arguments.length;
529
			for (int i = 0; i < argumentsLength; i++)
550
			for (int i = 0; i < argumentsLength; i++)
530
				arguments[i].traverse(visitor, blockScope);
551
				this.arguments[i].traverse(visitor, blockScope);
531
		}
552
		}
532
	}
553
	}
533
	visitor.endVisit(this, blockScope);
554
	visitor.endVisit(this, blockScope);

Return to bug 175409