*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
-import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
FlowContext flowContext,
FlowInfo flowInfo) {
- return expression
+ flowInfo = expression
.analyseCode(currentScope, flowContext, flowInfo)
.unconditionalInits();
+ expression.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+ return flowInfo;
}
- /**
- * Returns false if the instanceof unnecessary
- */
- public final boolean checkCastTypesCompatibility(
- BlockScope scope,
- TypeBinding castType,
- TypeBinding expressionType) {
-
- //A more complete version of this method is provided on
- //CastExpression (it deals with constant and need runtime checkcast)
-
- if (castType == expressionType) return false;
-
- //by grammatical construction, the base type check is not necessary
- if (castType == null || expressionType == null) return true;
-
- //-----------cast to something which is NOT a base type--------------------------
- if (expressionType == NullBinding) {
- // if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
- // needRuntimeCheckcast = true;
- // }
- return false; //null is compatible with every thing
- }
- if (expressionType.isBaseType()) {
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
-
- if (expressionType.isArrayType()) {
- if (castType == expressionType) return false; // identity conversion
-
- if (castType.isArrayType()) {
- //------- (castType.isArray) expressionType.isArray -----------
- TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
- if (exprElementType.isBaseType()) {
- // <---stop the recursion-------
- if (((ArrayBinding) castType).elementsType(scope) != exprElementType)
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
- // recursively on the elements...
- return checkCastTypesCompatibility(
- scope,
- ((ArrayBinding) castType).elementsType(scope),
- exprElementType);
- } else if (
- castType.isClass()) {
- //------(castType.isClass) expressionType.isArray ---------------
- if (castType.id == T_Object) {
- return false;
- }
- } else { //------- (castType.isInterface) expressionType.isArray -----------
- if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
- return true;
- }
- }
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
-
- if (expressionType.isClass()) {
- if (castType.isArrayType()) {
- // ---- (castType.isArray) expressionType.isClass -------
- if (expressionType.id == T_Object) { // potential runtime error
- return true;
- }
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
- if (expressionType.isCompatibleWith(castType)){ // no runtime error
- return false;
- }
- if (castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- return true;
- }
- } else { // ----- (castType.isInterface) expressionType.isClass -------
- if (expressionType.isCompatibleWith(castType))
- return false;
- if (!((ReferenceBinding) expressionType).isFinal()) {
- // a subclass may implement the interface ==> no check at compile time
- return true;
- }
- // no subclass for expressionType, thus compile-time check is valid
- }
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
-
- // if (expressionType.isInterface()) { cannot be anything else
- if (castType.isArrayType()) {
- // ----- (castType.isArray) expressionType.isInterface ------
- if (!(expressionType.id == T_JavaLangCloneable
- || expressionType.id == T_JavaIoSerializable)) {// potential runtime error
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- }
- return true;
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
- if (castType.id == T_Object) { // no runtime error
- return false;
- }
- if (((ReferenceBinding) castType).isFinal()) {
- // no subclass for castType, thus compile-time check is valid
- if (!castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- return true;
- }
- }
- } else { // ----- (castType.isInterface) expressionType.isInterface -------
- if (expressionType.isCompatibleWith(castType)) {
- return false;
- }
- if (!castType.isCompatibleWith(expressionType)) {
- MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
- MethodBinding[] expressionTypeMethods =
- ((ReferenceBinding) expressionType).methods();
- int exprMethodsLength = expressionTypeMethods.length;
- for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
- for (int j = 0; j < exprMethodsLength; j++) {
- if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
- && CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector)
- && castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
- scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
- }
- }
- }
- }
- return true;
- }
/**
* Code generation for instanceOfExpression
*
int pc = codeStream.position;
expression.generateCode(currentScope, codeStream, true);
codeStream.instance_of(type.resolvedType);
- if (!valueRequired)
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
codeStream.pop();
+ }
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$
return type.print(0, output);
}
-
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#reportIllegalCast(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+ public void reportIllegalCast(Scope scope, TypeBinding castType, TypeBinding expressionType) {
+ scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+ }
public TypeBinding resolveType(BlockScope scope) {
constant = NotAConstant;
TypeBinding expressionType = expression.resolveType(scope);
- TypeBinding checkType = type.resolveType(scope);
- if (expressionType == null || checkType == null)
+ TypeBinding checkedType = type.resolveType(scope, true /* check bounds*/);
+ if (expressionType == null || checkedType == null)
return null;
- boolean necessary = checkCastTypesCompatibility(scope, checkType, expressionType);
- if (!necessary) {
- scope.problemReporter().unnecessaryInstanceof(this, checkType);
+ if (checkedType.isTypeVariable() || checkedType.isBoundParameterizedType() || checkedType.isGenericType()) {
+ scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+ } else {
+ checkCastTypesCompatibility(scope, checkedType, expressionType, null);
}
return this.resolvedType = BooleanBinding;
}
-
+ /**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
+ */
+ public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
+ scope.problemReporter().unnecessaryInstanceof(this, castType);
+ }
public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {