X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fast%2FInstanceOfExpression.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fast%2FInstanceOfExpression.java;h=feacdaf8708f320eaf501391703e08900d3db56a;hb=040fa5af2cd00017cf3575950cdaade34a6d7f6c;hp=0000000000000000000000000000000000000000;hpb=a580fb8376d315d05e4d6bfdff9ff1101a151cd6;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java new file mode 100644 index 0000000..feacdaf --- /dev/null +++ b/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +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.*; +import org.eclipse.jdt.internal.compiler.lookup.*; + +public class InstanceOfExpression extends OperatorExpression { + + public Expression expression; + public TypeReference type; + + public InstanceOfExpression( + Expression expression, + TypeReference type, + int operator) { + + this.expression = expression; + this.type = type; + this.bits |= operator << OperatorSHIFT; + this.sourceStart = expression.sourceStart; + this.sourceEnd = type.sourceEnd; + } + + public FlowInfo analyseCode( + BlockScope currentScope, + FlowContext flowContext, + FlowInfo flowInfo) { + + return expression + .analyseCode(currentScope, flowContext, flowInfo) + .unconditionalInits(); + } + /** + * 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 + * + * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope + * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream + * @param valueRequired boolean + */ + public void generateCode( + BlockScope currentScope, + CodeStream codeStream, + boolean valueRequired) { + + int pc = codeStream.position; + expression.generateCode(currentScope, codeStream, true); + codeStream.instance_of(type.resolvedType); + if (!valueRequired) + codeStream.pop(); + codeStream.recordPositionsFrom(pc, this.sourceStart); + } + + public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) { + + expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$ + return type.print(0, output); + } + + public TypeBinding resolveType(BlockScope scope) { + + constant = NotAConstant; + TypeBinding expressionType = expression.resolveType(scope); + TypeBinding checkType = type.resolveType(scope); + if (expressionType == null || checkType == null) + return null; + + boolean necessary = checkCastTypesCompatibility(scope, checkType, expressionType); + if (!necessary) { + scope.problemReporter().unnecessaryInstanceof(this, checkType); + } + return this.resolvedType = BooleanBinding; + } + + public void traverse(ASTVisitor visitor, BlockScope scope) { + + if (visitor.visit(this, scope)) { + expression.traverse(visitor, scope); + type.traverse(visitor, scope); + } + visitor.endVisit(this, scope); + } +}