1 /*******************************************************************************
2 * Copyright (c) 2000, 2014 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Stephan Herrmann - Contributions for
11 * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
12 * bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
13 * bug 349326 - [1.7] new warning for missing try-with-resources
14 * bug 186342 - [compiler][null] Using annotations for null checking
15 * bug 358903 - Filter practically unimportant resource leak warnings
16 * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
17 * bug 370639 - [compiler][resource] restore the default for resource leak warnings
18 * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
19 * bug 388996 - [compiler][resource] Incorrect 'potential resource leak'
20 * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
21 * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
22 * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
23 * Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
24 * Bug 424727 - [compiler][null] NullPointerException in nullAnnotationUnsupportedLocation(ProblemReporter.java:5708)
25 * Bug 424710 - [1.8][compiler] CCE in SingleNameReference.localVariableBinding
26 * Bug 425152 - [1.8] [compiler] Lambda Expression not resolved but flow analyzed leading to NPE.
27 * Bug 424205 - [1.8] Cannot infer type for diamond type with lambda on method invocation
28 * Bug 424415 - [1.8][compiler] Eventual resolution of ReferenceExpression is not seen to be happening.
29 * Bug 426366 - [1.8][compiler] Type inference doesn't handle multiple candidate target types in outer overload context
30 * Bug 426290 - [1.8][compiler] Inference + overloading => wrong method resolution ?
31 * Bug 426764 - [1.8] Presence of conditional expression as method argument confuses compiler
32 * Bug 424930 - [1.8][compiler] Regression: "Cannot infer type arguments" error from compiler.
33 * Bug 427483 - [Java 8] Variables in lambdas sometimes can't be resolved
34 * Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
35 * Bug 426996 - [1.8][inference] try to avoid method Expression.unresolve()?
36 * Bug 428352 - [1.8][compiler] Resolution errors don't always surface
37 * Bug 429203 - [1.8][compiler] NPE in AllocationExpression.binding
38 * Bug 429430 - [1.8] Lambdas and method reference infer wrong exception type with generics (RuntimeException instead of IOException)
39 * Bug 434297 - [1.8] NPE in LamdaExpression.analyseCode with lamda expression nested in a conditional expression
40 * Jesper S Moller <jesper@selskabet.org> - Contributions for
41 * bug 378674 - "The method can be declared as static" is wrong
42 * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
43 * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
44 * Bug 409245 - [1.8][compiler] Type annotations dropped when call is routed through a synthetic bridge method
45 * Till Brychcy - Contributions for
46 * bug 413460 - NonNullByDefault is not inherited to Constructors when accessed via Class File
47 *******************************************************************************/
48 package org.eclipse.jdt.internal.compiler.ast;
49
50 import static org.eclipse.jdt.internal.compiler.ast.ExpressionContext.*;
51
52 import org.eclipse.jdt.core.compiler.IProblem;
53 import org.eclipse.jdt.internal.compiler.ASTVisitor;
54 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
55 import org.eclipse.jdt.internal.compiler.codegen.*;
56 import org.eclipse.jdt.internal.compiler.flow.*;
57 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
58 import org.eclipse.jdt.internal.compiler.impl.Constant;
59 import org.eclipse.jdt.internal.compiler.lookup.*;
60 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
61 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
62
63 public class AllocationExpression extends Expression implements Invocation {
64
65 public TypeReference type;
66 public Expression[] arguments;
67 public MethodBinding binding; // exact binding resulting from lookup
68 MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation
69 public TypeReference[] typeArguments;
70 public TypeBinding[] genericTypeArguments;
71 public FieldDeclaration enumConstant; // for enum constant initializations
72 protected TypeBinding typeExpected; // for <> inference
73 public boolean inferredReturnType;
74
75 public FakedTrackingVariable closeTracker; // when allocation a Closeable store a pre-liminary tracking variable here
76 private ExpressionContext expressionContext = VANILLA_CONTEXT;
77
78 // hold on to this context from invocation applicability inference until invocation type inference (per method candidate):
79 private SimpleLookupTable/*<PMB,IC18>*/ inferenceContexts;
80 protected InnerInferenceHelper innerInferenceHelper;
81 public boolean argumentsHaveErrors;
82
83 /** Record to keep state between different parts of resolution. */
84 ResolutionState suspendedResolutionState;
85 class ResolutionState {
86 BlockScope scope;
87 boolean isDiamond;
88 boolean diamondNeedsDeferring;
89 boolean argsContainCast;
90 boolean cannotInferDiamond; // request the an error be reported in due time
91 TypeBinding[] argumentTypes;
92 boolean hasReportedError;
93
ResolutionState(BlockScope scope, boolean isDiamond, boolean diamonNeedsDeferring, boolean argsContainCast, TypeBinding[] argumentTypes)94 ResolutionState(BlockScope scope, boolean isDiamond, boolean diamonNeedsDeferring,
95 boolean argsContainCast, TypeBinding[] argumentTypes)
96 {
97 this.scope = scope;
98 this.isDiamond = isDiamond;
99 this.diamondNeedsDeferring = diamonNeedsDeferring;
100 this.argsContainCast = argsContainCast;
101 this.argumentTypes = argumentTypes;
102 }
103 }
104
analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo)105 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
106 // check captured variables are initialized in current context (26134)
107 checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo);
108
109 // process arguments
110 if (this.arguments != null) {
111 boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks;
112 boolean hasResourceWrapperType = analyseResources
113 && this.resolvedType instanceof ReferenceBinding
114 && ((ReferenceBinding)this.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable);
115 for (int i = 0, count = this.arguments.length; i < count; i++) {
116 flowInfo =
117 this.arguments[i]
118 .analyseCode(currentScope, flowContext, flowInfo)
119 .unconditionalInits();
120 // if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
121 if (analyseResources && !hasResourceWrapperType) { // allocation of wrapped closeables is analyzed specially
122 flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, flowContext, false);
123 }
124 this.arguments[i].checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
125 }
126 analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
127 }
128
129 // record some dependency information for exception types
130 ReferenceBinding[] thrownExceptions;
131 if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
132 if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) {
133 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6
134 thrownExceptions = currentScope.environment().convertToRawTypes(this.binding.thrownExceptions, true, true);
135 }
136 // check exception handling
137 flowContext.checkExceptionHandlers(
138 thrownExceptions,
139 this,
140 flowInfo.unconditionalCopy(),
141 currentScope);
142 }
143
144 // after having analysed exceptions above start tracking newly allocated resource:
145 if (currentScope.compilerOptions().analyseResourceLeaks && FakedTrackingVariable.isAnyCloseable(this.resolvedType))
146 FakedTrackingVariable.analyseCloseableAllocation(currentScope, flowInfo, this);
147
148 if (this.binding.declaringClass.isMemberType() && !this.binding.declaringClass.isStatic()) {
149 // allocating a non-static member type without an enclosing instance of parent type
150 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=335845
151 currentScope.tagAsAccessingEnclosingInstanceStateOf(this.binding.declaringClass.enclosingType(), false /* type variable access */);
152 // Reviewed for https://bugs.eclipse.org/bugs/show_bug.cgi?id=378674 :
153 // The corresponding problem (when called from static) is not produced until during code generation
154 }
155 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
156 manageSyntheticAccessIfNecessary(currentScope, flowInfo);
157
158 // account for possible exceptions thrown by the constructor
159 flowContext.recordAbruptExit(); // TODO whitelist of ctors that cannot throw any exc.??
160
161 return flowInfo;
162 }
163
checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo)164 public void checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo) {
165 if (((checkedType.tagBits & ( TagBits.AnonymousTypeMask|TagBits.LocalTypeMask)) == TagBits.LocalTypeMask)
166 && !currentScope.isDefinedInType(checkedType)) { // only check external allocations
167 NestedTypeBinding nestedType = (NestedTypeBinding) checkedType;
168 SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
169 if (syntheticArguments != null)
170 for (int i = 0, count = syntheticArguments.length; i < count; i++){
171 SyntheticArgumentBinding syntheticArgument = syntheticArguments[i];
172 LocalVariableBinding targetLocal;
173 if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) continue;
174 if (targetLocal.declaration != null && !flowInfo.isDefinitelyAssigned(targetLocal)){
175 currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
176 }
177 }
178 }
179 }
180
enclosingInstance()181 public Expression enclosingInstance() {
182 return null;
183 }
184
generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired)185 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
186 if (!valueRequired)
187 currentScope.problemReporter().unusedObjectAllocation(this);
188
189 int pc = codeStream.position;
190 MethodBinding codegenBinding = this.binding.original();
191 ReferenceBinding allocatedType = codegenBinding.declaringClass;
192
193 codeStream.new_(this.type, allocatedType);
194 boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
195 if (valueRequired || isUnboxing) {
196 codeStream.dup();
197 }
198 // better highlight for allocation: display the type individually
199 if (this.type != null) { // null for enum constant body
200 codeStream.recordPositionsFrom(pc, this.type.sourceStart);
201 } else {
202 // push enum constant name and ordinal
203 codeStream.ldc(String.valueOf(this.enumConstant.name));
204 codeStream.generateInlinedValue(this.enumConstant.binding.id);
205 }
206
207 // handling innerclass instance allocation - enclosing instance arguments
208 if (allocatedType.isNestedType()) {
209 codeStream.generateSyntheticEnclosingInstanceValues(
210 currentScope,
211 allocatedType,
212 enclosingInstance(),
213 this);
214 }
215 // generate the arguments for constructor
216 generateArguments(this.binding, this.arguments, currentScope, codeStream);
217 // handling innerclass instance allocation - outer local arguments
218 if (allocatedType.isNestedType()) {
219 codeStream.generateSyntheticOuterArgumentValues(
220 currentScope,
221 allocatedType,
222 this);
223 }
224 // invoke constructor
225 if (this.syntheticAccessor == null) {
226 codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, null /* default declaringClass */, this.typeArguments);
227 } else {
228 // synthetic accessor got some extra arguments appended to its signature, which need values
229 for (int i = 0,
230 max = this.syntheticAccessor.parameters.length - codegenBinding.parameters.length;
231 i < max;
232 i++) {
233 codeStream.aconst_null();
234 }
235 codeStream.invoke(Opcodes.OPC_invokespecial, this.syntheticAccessor, null /* default declaringClass */, this.typeArguments);
236 }
237 if (valueRequired) {
238 codeStream.generateImplicitConversion(this.implicitConversion);
239 } else if (isUnboxing) {
240 // conversion only generated if unboxing
241 codeStream.generateImplicitConversion(this.implicitConversion);
242 switch (postConversionType(currentScope).id) {
243 case T_long :
244 case T_double :
245 codeStream.pop2();
246 break;
247 default :
248 codeStream.pop();
249 }
250 }
251 codeStream.recordPositionsFrom(pc, this.sourceStart);
252 }
253
254 /**
255 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
256 */
genericTypeArguments()257 public TypeBinding[] genericTypeArguments() {
258 return this.genericTypeArguments;
259 }
260
isSuperAccess()261 public boolean isSuperAccess() {
262 return false;
263 }
264
isTypeAccess()265 public boolean isTypeAccess() {
266 return true;
267 }
268
269 /* Inner emulation consists in either recording a dependency
270 * link only, or performing one level of propagation.
271 *
272 * Dependency mechanism is used whenever dealing with source target
273 * types, since by the time we reach them, we might not yet know their
274 * exact need.
275 */
manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo)276 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
277 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return;
278 ReferenceBinding allocatedTypeErasure = (ReferenceBinding) this.binding.declaringClass.erasure();
279
280 // perform some emulation work in case there is some and we are inside a local type only
281 if (allocatedTypeErasure.isNestedType()
282 && (currentScope.enclosingSourceType().isLocalType() || currentScope.isLambdaScope())) {
283
284 if (allocatedTypeErasure.isLocalType()) {
285 ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false);
286 // request cascade of accesses
287 } else {
288 // locally propagate, since we already now the desired shape for sure
289 currentScope.propagateInnerEmulation(allocatedTypeErasure, false);
290 // request cascade of accesses
291 }
292 }
293 }
294
manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo)295 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
296 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return;
297 // if constructor from parameterized type got found, use the original constructor at codegen time
298 MethodBinding codegenBinding = this.binding.original();
299
300 ReferenceBinding declaringClass;
301 if (codegenBinding.isPrivate() && TypeBinding.notEquals(currentScope.enclosingSourceType(), (declaringClass = codegenBinding.declaringClass))) {
302
303 // from 1.4 on, local type constructor can lose their private flag to ease emulation
304 if ((declaringClass.tagBits & TagBits.IsLocalType) != 0 && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
305 // constructor will not be dumped as private, no emulation required thus
306 codegenBinding.tagBits |= TagBits.ClearPrivateModifier;
307 } else {
308 this.syntheticAccessor = ((SourceTypeBinding) declaringClass).addSyntheticMethod(codegenBinding, isSuperAccess());
309 currentScope.problemReporter().needToEmulateMethodAccess(codegenBinding, this);
310 }
311 }
312 }
313
printExpression(int indent, StringBuffer output)314 public StringBuffer printExpression(int indent, StringBuffer output) {
315 if (this.type != null) { // type null for enum constant initializations
316 output.append("new "); //$NON-NLS-1$
317 }
318 if (this.typeArguments != null) {
319 output.append('<');
320 int max = this.typeArguments.length - 1;
321 for (int j = 0; j < max; j++) {
322 this.typeArguments[j].print(0, output);
323 output.append(", ");//$NON-NLS-1$
324 }
325 this.typeArguments[max].print(0, output);
326 output.append('>');
327 }
328 if (this.type != null) { // type null for enum constant initializations
329 this.type.printExpression(0, output);
330 }
331 output.append('(');
332 if (this.arguments != null) {
333 for (int i = 0; i < this.arguments.length; i++) {
334 if (i > 0) output.append(", "); //$NON-NLS-1$
335 this.arguments[i].printExpression(0, output);
336 }
337 }
338 return output.append(')');
339 }
340
resolveType(BlockScope scope)341 public TypeBinding resolveType(BlockScope scope) {
342 // Propagate the type checking to the arguments, and check if the constructor is defined.
343 final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
344 final CompilerOptions compilerOptions = scope.compilerOptions();
345 boolean diamondNeedsDeferring = false;
346 long sourceLevel = compilerOptions.sourceLevel;
347 if (this.constant != Constant.NotAConstant) {
348 this.constant = Constant.NotAConstant;
349 if (this.type == null) {
350 // initialization of an enum constant
351 this.resolvedType = scope.enclosingReceiverType();
352 } else {
353 this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
354 if (isDiamond && this.typeExpected == null && this.expressionContext == INVOCATION_CONTEXT && sourceLevel >= ClassFileConstants.JDK1_8) {
355 if (this.resolvedType != null && this.resolvedType.isValidBinding())
356 diamondNeedsDeferring = true;
357 }
358 }
359 } else {
360 this.resolvedType = this.type.resolvedType;
361 }
362
363 if (this.type != null) {
364 checkIllegalNullAnnotation(scope, this.resolvedType);
365 checkParameterizedAllocation: {
366 if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
367 ReferenceBinding currentType = (ReferenceBinding)this.resolvedType;
368 if (currentType == null) return currentType;
369 do {
370 // isStatic() is answering true for toplevel types
371 if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation;
372 if (currentType.isRawType()) break checkParameterizedAllocation;
373 } while ((currentType = currentType.enclosingType())!= null);
374 ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type;
375 for (int i = qRef.typeArguments.length - 2; i >= 0; i--) {
376 if (qRef.typeArguments[i] != null) {
377 scope.problemReporter().illegalQualifiedParameterizedTypeAllocation(this.type, this.resolvedType);
378 break;
379 }
380 }
381 }
382 }
383 }
384 // will check for null after args are resolved
385
386 // resolve type arguments (for generic constructor call)
387 if (this.typeArguments != null) {
388 int length = this.typeArguments.length;
389 this.argumentsHaveErrors = sourceLevel < ClassFileConstants.JDK1_5;
390 this.genericTypeArguments = new TypeBinding[length];
391 for (int i = 0; i < length; i++) {
392 TypeReference typeReference = this.typeArguments[i];
393 if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) {
394 this.argumentsHaveErrors = true;
395 }
396 if (this.argumentsHaveErrors && typeReference instanceof Wildcard) {
397 scope.problemReporter().illegalUsageOfWildcard(typeReference);
398 }
399 }
400 if (isDiamond) {
401 scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
402 return null;
403 }
404 if (this.argumentsHaveErrors) {
405 if (this.arguments != null) { // still attempt to resolve arguments
406 for (int i = 0, max = this.arguments.length; i < max; i++) {
407 this.arguments[i].resolveType(scope);
408 }
409 }
410 return null;
411 }
412 }
413
414 // buffering the arguments' types
415 boolean argsContainCast = false;
416 TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
417 if (this.arguments != null) {
418 this.argumentsHaveErrors = false;
419 int length = this.arguments.length;
420 argumentTypes = new TypeBinding[length];
421 for (int i = 0; i < length; i++) {
422 Expression argument = this.arguments[i];
423 if (argument instanceof CastExpression) {
424 argument.bits |= DisableUnnecessaryCastCheck; // will check later on
425 argsContainCast = true;
426 }
427 argument.setExpressionContext(INVOCATION_CONTEXT);
428 if (this.arguments[i].resolvedType != null)
429 scope.problemReporter().genericInferenceError("Argument was unexpectedly found resolved", this); //$NON-NLS-1$
430 if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
431 this.argumentsHaveErrors = true;
432 }
433 if (sourceLevel >= ClassFileConstants.JDK1_8 && (argument.isPolyExpression() || ((argument instanceof Invocation) && ((Invocation) argument).usesInference()))) {
434 if (this.innerInferenceHelper == null)
435 this.innerInferenceHelper = new InnerInferenceHelper();
436 }
437 }
438 if (this.argumentsHaveErrors) {
439 /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case.
440 No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do
441 not return the partially resolved type.
442 */
443 if (isDiamond) {
444 return null; // not the partially cooked this.resolvedType
445 }
446 if (this.resolvedType instanceof ReferenceBinding) {
447 // record a best guess, for clients who need hint about possible constructor match
448 TypeBinding[] pseudoArgs = new TypeBinding[length];
449 for (int i = length; --i >= 0;) {
450 pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
451 }
452 this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this, false);
453 if (this.binding != null && !this.binding.isValidBinding()) {
454 MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
455 // record the closest match, for clients who may still need hint about possible method match
456 if (closestMatch != null) {
457 if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
458 // shouldn't return generic method outside its context, rather convert it to raw method (175409)
459 closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null);
460 }
461 this.binding = closestMatch;
462 MethodBinding closestMatchOriginal = closestMatch.original();
463 if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) {
464 // ignore cases where method is used from within inside itself (e.g. direct recursions)
465 closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
466 }
467 }
468 }
469 }
470 return this.resolvedType;
471 }
472 }
473 if (this.resolvedType == null || !this.resolvedType.isValidBinding()) {
474 return null;
475 }
476
477 // null type denotes fake allocation for enum constant inits
478 if (this.type != null && !this.resolvedType.canBeInstantiated()) {
479 scope.problemReporter().cannotInstantiate(this.type, this.resolvedType);
480 return this.resolvedType;
481 }
482 ResolutionState state = new ResolutionState(scope, isDiamond, diamondNeedsDeferring, argsContainCast, argumentTypes);
483 if (diamondNeedsDeferring) {
484 this.suspendedResolutionState = state; // resolving to be continued later (via binding(TypeBinding targetType)).
485 return new PolyTypeBinding(this);
486 }
487
488 if (!resolvePart2(state))
489 return null;
490 return resolvePart3(state);
491 }
492
493 /** Second part of resolving that may happen multiple times during overload resolution. */
494 boolean resolvePart2(ResolutionState state) {
495 // TODO: all information persisted during this method may need to be stored per targetType?
496 if (state.isDiamond) {
497 ReferenceBinding genericType = ((ParameterizedTypeBinding) this.resolvedType).genericType();
498 TypeBinding [] inferredTypes = inferElidedTypes((ParameterizedTypeBinding) this.resolvedType, this.resolvedType.enclosingType(), state.argumentTypes, state.scope);
499 if (inferredTypes == null) {
500 if (!state.diamondNeedsDeferring) {
501 state.scope.problemReporter().cannotInferElidedTypes(this);
502 state.hasReportedError = true;
503 this.resolvedType = null;
504 } else {
505 state.cannotInferDiamond = true; // defer reporting
506 }
507 return false;
508 }
509 this.resolvedType = this.type.resolvedType = state.scope.environment().createParameterizedType(genericType, inferredTypes, ((ParameterizedTypeBinding) this.resolvedType).enclosingType());
510 state.cannotInferDiamond = false;
511 }
512 ReferenceBinding receiverType = (ReferenceBinding) this.resolvedType;
513 this.binding = findConstructorBinding(state.scope, this, receiverType, state.argumentTypes);
514 return true;
515 }
516
517 /** Final part of resolving (once): check and report various error conditions. */
518 TypeBinding resolvePart3(ResolutionState state) {
519 if (this.suspendedResolutionState != null && this.suspendedResolutionState.hasReportedError)
520 return this.resolvedType;
521 this.suspendedResolutionState = null;
522 if (state.cannotInferDiamond) {
523 state.scope.problemReporter().cannotInferElidedTypes(this);
524 return this.resolvedType = null;
525 }
526 ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
527 if (!this.binding.isValidBinding()) {
528 if (this.binding.declaringClass == null) {
529 this.binding.declaringClass = allocationType;
530 }
531 if (this.type != null && !this.type.resolvedType.isValidBinding()) {
532 return null;
533 }
534 state.scope.problemReporter().invalidConstructor(this, this.binding);
535 return this.resolvedType;
536 }
537 if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
538 state.scope.problemReporter().missingTypeInConstructor(this, this.binding);
539 }
540 if (isMethodUseDeprecated(this.binding, state.scope, true)) {
541 state.scope.problemReporter().deprecatedMethod(this.binding, this);
542 }
543 if (checkInvocationArguments(state.scope, null, allocationType, this.binding, this.arguments, state.argumentTypes, state.argsContainCast, this)) {
544 this.bits |= ASTNode.Unchecked;
545 }
546 if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
547 state.scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments);
548 }
549 if (!state.isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) {
550 checkTypeArgumentRedundancy((ParameterizedTypeBinding) this.resolvedType, this.resolvedType.enclosingType(), state.argumentTypes, state.scope);
551 }
552 CompilerOptions compilerOptions = state.scope.compilerOptions();
553 if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
554 new ImplicitNullAnnotationVerifier(state.scope.environment(), compilerOptions.inheritNullAnnotations)
555 .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, state.scope);
556 }
557 recordExceptionsForEnclosingLambda(state.scope, this.binding.thrownExceptions);
558 return allocationType;
559 }
560
561 /**
562 * Check if 'allocationType' illegally has a top-level null annotation.
563 */
564 void checkIllegalNullAnnotation(BlockScope scope, TypeBinding allocationType) {
565 if (allocationType != null) {
566 // only check top-level null annotation (annots on details are OK):
567 long nullTagBits = allocationType.tagBits & TagBits.AnnotationNullMASK;
568 if (nullTagBits != 0) {
569 Annotation annotation = this.type.findAnnotation(nullTagBits);
570 if (annotation != null)
571 scope.problemReporter().nullAnnotationUnsupportedLocation(annotation);
572 }
573 }
574 }
575
576 public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) {
577 /* Given the allocation type and the arguments to the constructor, see if we can synthesize a generic static factory
578 method that would, given the argument types and the invocation site, manufacture a parameterized object of type allocationType.
579 If we are successful then by design and construction, the parameterization of the return type of the factory method is identical
580 to the types elided in the <>.
581 */
582 MethodBinding factory = scope.getStaticFactory(allocationType, enclosingType, argumentTypes, this);
583 if (factory instanceof ParameterizedGenericMethodBinding && factory.isValidBinding()) {
584 ParameterizedGenericMethodBinding genericFactory = (ParameterizedGenericMethodBinding) factory;
585 this.inferredReturnType = genericFactory.inferredReturnType;
586 // this is our last chance to inspect the result of the inference that is connected to the throw-away factory binding
587 InferenceContext18 infCtx18 = getInferenceContext(genericFactory);
588 if (infCtx18 != null && infCtx18.stepCompleted == InferenceContext18.BINDINGS_UPDATED) {
589 // refresh argumentTypes from updated bindings in arguments:
590 // (this shouldn't be strictly necessary, as FunctionExpression.isCompatibleWith() should give the same result,
591 // but it's probably be a good idea to avoid the necessity to call isCompatibleWith() in the first place).
592 for (int i = 0; i < argumentTypes.length; i++) {
593 if (argumentTypes[i] instanceof PolyTypeBinding)
594 argumentTypes[i] = this.arguments[i].resolvedType;
595 }
596 }
597 return ((ParameterizedTypeBinding)factory.returnType).arguments;
598 }
599 return null;
600 }
601
602 public void checkTypeArgumentRedundancy(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) {
603 if ((scope.problemReporter().computeSeverity(IProblem.RedundantSpecificationOfTypeArguments) == ProblemSeverities.Ignore) || scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return;
604 if (allocationType.arguments == null) return; // raw binding
605 if (this.genericTypeArguments != null) return; // diamond can't occur with explicit type args for constructor
606 if (this.type == null) return;
607 if (argumentTypes == Binding.NO_PARAMETERS && this.typeExpected instanceof ParameterizedTypeBinding) {
608 ParameterizedTypeBinding expected = (ParameterizedTypeBinding) this.typeExpected;
609 if (expected.arguments != null && allocationType.arguments.length == expected.arguments.length) {
610 // check the case when no ctor takes no params and inference uses the expected type directly
611 // eg. X<String> x = new X<String>()
612 int i;
613 for (i = 0; i < allocationType.arguments.length; i++) {
614 if (TypeBinding.notEquals(allocationType.arguments[i], expected.arguments[i]))
615 break;
616 }
617 if (i == allocationType.arguments.length) {
618 scope.problemReporter().redundantSpecificationOfTypeArguments(this.type, allocationType.arguments);
619 return;
620 }
621 }
622 }
623 TypeBinding [] inferredTypes;
624 int previousBits = this.type.bits;
625 try {
626 // checking for redundant type parameters must fake a diamond,
627 // so we infer the same results as we would get with a diamond in source code:
628 this.type.bits |= IsDiamond;
629 inferredTypes = inferElidedTypes(allocationType, enclosingType, argumentTypes, scope);
630 } finally {
631 // reset effects of inference
632 this.type.bits = previousBits;
633 }
634 if (inferredTypes == null) {
635 return;
636 }
637 for (int i = 0; i < inferredTypes.length; i++) {
638 if (TypeBinding.notEquals(inferredTypes[i], allocationType.arguments[i]))
639 return;
640 }
641 scope.problemReporter().redundantSpecificationOfTypeArguments(this.type, allocationType.arguments);
642 }
643
644 public void setActualReceiverType(ReferenceBinding receiverType) {
645 // ignored
646 }
647
648 public void setDepth(int i) {
649 // ignored
650 }
651
652 public void setFieldIndex(int i) {
653 // ignored
654 }
655
656 public void traverse(ASTVisitor visitor, BlockScope scope) {
657 if (visitor.visit(this, scope)) {
658 if (this.typeArguments != null) {
659 for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) {
660 this.typeArguments[i].traverse(visitor, scope);
661 }
662 }
663 if (this.type != null) { // enum constant scenario
664 this.type.traverse(visitor, scope);
665 }
666 if (this.arguments != null) {
667 for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++)
668 this.arguments[i].traverse(visitor, scope);
669 }
670 }
671 visitor.endVisit(this, scope);
672 }
673 /**
674 * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
675 */
676 public void setExpectedType(TypeBinding expectedType) {
677 this.typeExpected = expectedType;
678 }
679
680 public void setExpressionContext(ExpressionContext context) {
681 this.expressionContext = context;
682 }
683
684 public boolean isPolyExpression() {
685 return isPolyExpression(this.binding);
686 }
687 public boolean isPolyExpression(MethodBinding method) {
688 return (this.expressionContext == ASSIGNMENT_CONTEXT || this.expressionContext == INVOCATION_CONTEXT) &&
689 this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
690 }
691
692 /**
693 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#invocationTargetType()
694 */
695 public TypeBinding invocationTargetType() {
696 return this.typeExpected;
697 }
698
699 public boolean statementExpression() {
700 return true;
701 }
702
703 //-- interface Invocation: --
704 public MethodBinding binding(TypeBinding targetType, boolean reportErrors, Scope scope) {
705 if (this.suspendedResolutionState != null && targetType != null) {
706 setExpectedType(targetType);
707 if (!resolvePart2(this.suspendedResolutionState)) {
708 if (reportErrors && !this.suspendedResolutionState.hasReportedError) {
709 if (this.suspendedResolutionState.cannotInferDiamond)
710 scope.problemReporter().cannotInferElidedTypes(this);
711 else
712 scope.problemReporter().genericInferenceError("constructor is unexpectedly unresolved", this); //$NON-NLS-1$
713 this.suspendedResolutionState.hasReportedError = true;
714 }
715 return null;
716 }
717 }
718 if (reportErrors && this.binding != null && !this.binding.isValidBinding()) {
719 if (this.binding.declaringClass == null)
720 this.binding.declaringClass = (ReferenceBinding) this.resolvedType;
721 if (this.suspendedResolutionState != null) {
722 scope.problemReporter().invalidConstructor(this, this.binding);
723 this.suspendedResolutionState.hasReportedError = true;
724 }
725 }
726 return this.binding;
727 }
728 public TypeBinding checkAgainstFinalTargetType(TypeBinding targetType, Scope scope) {
729 this.typeExpected = targetType;
730 boolean needsUpdate = this.binding == null || // not yet resolved
731 (this.resolvedType != null && targetType != null && !this.resolvedType.isCompatibleWith(targetType)); // previous attempt was wrong
732 if (needsUpdate && this.suspendedResolutionState != null && !this.suspendedResolutionState.hasReportedError) {
733 // Attempt to resolve half resolved diamond
734 resolvePart2(this.suspendedResolutionState);
735 }
736 // confer MessageSend.checkAgainstFinalTargetType(,,):
737 if (this.binding instanceof ParameterizedGenericMethodBinding) {
738 InferenceContext18 ctx = getInferenceContext((ParameterizedMethodBinding) this.binding);
739 if (ctx != null && ctx.stepCompleted < InferenceContext18.TYPE_INFERRED) {
740 this.typeExpected = targetType;
741 MethodBinding updatedBinding = ctx.inferInvocationType(this, (ParameterizedGenericMethodBinding) this.binding);
742 if (updateBindings(updatedBinding, targetType)) {
743 ASTNode.resolvePolyExpressionArguments(this, updatedBinding, scope);
744 }
745 }
746 }
747 if (this.suspendedResolutionState != null) {
748 return resolvePart3(this.suspendedResolutionState);
749 }
750 return this.resolvedType;
751 }
752 public Expression[] arguments() {
753 return this.arguments;
754 }
755
756 public boolean updateBindings(MethodBinding updatedBinding, TypeBinding targetType) {
757 boolean hasUpdate = this.binding != updatedBinding;
758 if (this.inferenceContexts != null && this.binding.original() == updatedBinding.original()) {
759 InferenceContext18 ctx = (InferenceContext18)this.inferenceContexts.get(this.binding);
760 if (ctx != null && updatedBinding instanceof ParameterizedGenericMethodBinding) {
761 this.inferenceContexts.put(updatedBinding, ctx);
762 // solution may have come from an outer inference, mark now that this (inner) is done (but not deep inners):
763 hasUpdate |= ctx.registerSolution(targetType, updatedBinding);
764 }
765 }
766 this.binding = updatedBinding;
767 this.resolvedType = updatedBinding.declaringClass;
768 return hasUpdate;
769 }
770 public void registerInferenceContext(ParameterizedGenericMethodBinding method, InferenceContext18 infCtx18) {
771 if (this.inferenceContexts == null)
772 this.inferenceContexts = new SimpleLookupTable();
773 this.inferenceContexts.put(method, infCtx18);
774 MethodBinding original = method.original();
775 if (original instanceof SyntheticFactoryMethodBinding) {
776 SyntheticFactoryMethodBinding synthOriginal = (SyntheticFactoryMethodBinding)original;
777 ParameterizedMethodBinding parameterizedCtor = synthOriginal.applyTypeArgumentsOnConstructor(method.typeArguments);
778 this.inferenceContexts.put(parameterizedCtor, infCtx18);
779 }
780 }
781 public boolean usesInference() {
782 return (this.binding instanceof ParameterizedGenericMethodBinding)
783 && getInferenceContext((ParameterizedGenericMethodBinding) this.binding) != null;
784 }
785 public InferenceContext18 getInferenceContext(ParameterizedMethodBinding method) {
786 if (this.inferenceContexts == null)
787 return null;
788 return (InferenceContext18) this.inferenceContexts.get(method);
789 }
790 public boolean innersNeedUpdate() {
791 return this.innerInferenceHelper != null;
792 }
793 public void innerUpdateDone() {
794 this.innerInferenceHelper = null;
795 }
796 public InnerInferenceHelper innerInferenceHelper() {
797 return this.innerInferenceHelper;
798 }
799
800 //-- interface InvocationSite: --
801 public ExpressionContext getExpressionContext() {
802 return this.expressionContext;
803 }
804 public InferenceContext18 freshInferenceContext(Scope scope) {
805 return new InferenceContext18(scope, this.arguments, this);
806 }
807 }
808