001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012: import org.eclipse.jdt.internal.compiler.ASTVisitor;
013: import org.eclipse.jdt.internal.compiler.codegen.*;
014: import org.eclipse.jdt.internal.compiler.flow.*;
015: import org.eclipse.jdt.internal.compiler.impl.Constant;
016: import org.eclipse.jdt.internal.compiler.lookup.*;
017:
018: public class InstanceOfExpression extends OperatorExpression {
019:
020: public Expression expression;
021: public TypeReference type;
022:
023: public InstanceOfExpression(Expression expression,
024: TypeReference type) {
025:
026: this .expression = expression;
027: this .type = type;
028: type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
029: this .bits |= INSTANCEOF << OperatorSHIFT;
030: this .sourceStart = expression.sourceStart;
031: this .sourceEnd = type.sourceEnd;
032: }
033:
034: public FlowInfo analyseCode(BlockScope currentScope,
035: FlowContext flowContext, FlowInfo flowInfo) {
036: LocalVariableBinding local = this .expression
037: .localVariableBinding();
038: if (local != null
039: && (local.type.tagBits & TagBits.IsBaseType) == 0) {
040: flowContext.recordUsingNullReference(currentScope, local,
041: this .expression, FlowContext.CAN_ONLY_NULL
042: | FlowContext.IN_INSTANCEOF, flowInfo);
043: flowInfo = expression.analyseCode(currentScope,
044: flowContext, flowInfo).unconditionalInits();
045: FlowInfo initsWhenTrue = flowInfo.copy();
046: initsWhenTrue.markAsComparedEqualToNonNull(local);
047: // no impact upon enclosing try context
048: return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
049: }
050: return expression.analyseCode(currentScope, flowContext,
051: flowInfo).unconditionalInits();
052: }
053:
054: /**
055: * Code generation for instanceOfExpression
056: *
057: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
058: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
059: * @param valueRequired boolean
060: */
061: public void generateCode(BlockScope currentScope,
062: CodeStream codeStream, boolean valueRequired) {
063:
064: int pc = codeStream.position;
065: expression.generateCode(currentScope, codeStream, true);
066: codeStream.instance_of(type.resolvedType);
067: if (valueRequired) {
068: codeStream.generateImplicitConversion(implicitConversion);
069: } else {
070: codeStream.pop();
071: }
072: codeStream.recordPositionsFrom(pc, this .sourceStart);
073: }
074:
075: public StringBuffer printExpressionNoParenthesis(int indent,
076: StringBuffer output) {
077:
078: expression.printExpression(indent, output).append(
079: " instanceof "); //$NON-NLS-1$
080: return type.print(0, output);
081: }
082:
083: public TypeBinding resolveType(BlockScope scope) {
084:
085: constant = Constant.NotAConstant;
086: TypeBinding expressionType = expression.resolveType(scope);
087: TypeBinding checkedType = type
088: .resolveType(scope, true /* check bounds*/);
089: if (expressionType == null || checkedType == null)
090: return null;
091:
092: if (!checkedType.isReifiable()) {
093: scope.problemReporter().illegalInstanceOfGenericType(
094: checkedType, this );
095: } else if ((expressionType != TypeBinding.NULL && expressionType
096: .isBaseType()) // disallow autoboxing
097: || !checkCastTypesCompatibility(scope, checkedType,
098: expressionType, null)) {
099: scope.problemReporter().notCompatibleTypesError(this ,
100: expressionType, checkedType);
101: }
102: return this .resolvedType = TypeBinding.BOOLEAN;
103: }
104:
105: /**
106: * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
107: */
108: public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
109: // null is not instanceof Type, recognize direct scenario
110: if (expression.resolvedType != TypeBinding.NULL)
111: scope.problemReporter().unnecessaryInstanceof(this ,
112: castType);
113: }
114:
115: public void traverse(ASTVisitor visitor, BlockScope scope) {
116:
117: if (visitor.visit(this, scope)) {
118: expression.traverse(visitor, scope);
119: type.traverse(visitor, scope);
120: }
121: visitor.endVisit(this, scope);
122: }
123: }
|