X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/CastExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/CastExpression.java index e103ccc..65e8268 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/CastExpression.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/CastExpression.java @@ -1,292 +1,64 @@ -/******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html - * - * Contributors: - * IBM Corporation - initial API and implementation - ******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; -import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor; -import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream; -import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; -import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; -import net.sourceforge.phpdt.internal.compiler.impl.Constant; -import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding; -import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypeBinding; -import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; -import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding; -import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; -import net.sourceforge.phpdt.internal.compiler.lookup.Scope; -import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; +import java.util.List; +/** + * This is a cast expression. + * @author Matthieu Casanova + */ public class CastExpression extends Expression { - public Expression expression; - public Expression type; - public boolean needRuntimeCheckcast; - public TypeBinding castTb; - - //expression.implicitConversion holds the cast for baseType casting - public CastExpression(Expression e, Expression t) { - expression = e; - type = t; - - //due to the fact an expression may start with ( and that a cast also start with ( - //the field is an expression....it can be a TypeReference OR a NameReference Or - //an expression <--this last one is invalid....... - - // :-( ............. - - //if (type instanceof TypeReference ) - // flag = IsTypeReference ; - //else - // if (type instanceof NameReference) - // flag = IsNameReference ; - // else - // flag = IsExpression ; - - } - - public FlowInfo analyseCode( - BlockScope currentScope, - FlowContext flowContext, - FlowInfo flowInfo) { - - return expression - .analyseCode(currentScope, flowContext, flowInfo) - .unconditionalInits(); - } - - public final void areTypesCastCompatible( - BlockScope scope, - TypeBinding castTb, - TypeBinding expressionTb) { - - // see specifications p.68 - // handle errors and process constant when needed - - // if either one of the type is null ==> - // some error has been already reported some where ==> - // we then do not report an obvious-cascade-error. - - needRuntimeCheckcast = false; - if (castTb == null || expressionTb == null) - return; - if (castTb.isBaseType()) { - if (expressionTb.isBaseType()) { - if (expressionTb == castTb) { - constant = expression.constant; //use the same constant - return; - } - if (BlockScope.areTypesCompatible(expressionTb, castTb) - || BaseTypeBinding.isNarrowing(castTb.id, expressionTb.id)) { - expression.implicitConversion = (castTb.id << 4) + expressionTb.id; - if (expression.constant != Constant.NotAConstant) - constant = expression.constant.castTo(expression.implicitConversion); - return; - } - } - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } - - //-----------cast to something which is NOT a base type-------------------------- - if (expressionTb == NullBinding) - return; //null is compatible with every thing - - if (expressionTb.isBaseType()) { - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } - - if (expressionTb.isArrayType()) { - if (castTb.isArrayType()) { - //------- (castTb.isArray) expressionTb.isArray ----------- - TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope); - if (expressionEltTb.isBaseType()) { - // <---stop the recursion------- - if (((ArrayBinding) castTb).elementsType(scope) == expressionEltTb) - needRuntimeCheckcast = true; - else - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } - // recursively on the elements... - areTypesCastCompatible( - scope, - ((ArrayBinding) castTb).elementsType(scope), - expressionEltTb); - return; - } else if ( - castTb.isClass()) { - //------(castTb.isClass) expressionTb.isArray --------------- - if (scope.isJavaLangObject(castTb)) - return; - } else { //------- (castTb.isInterface) expressionTb.isArray ----------- - if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) { - needRuntimeCheckcast = true; - return; - } - } - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } - - if (expressionTb.isClass()) { - if (castTb.isArrayType()) { - // ---- (castTb.isArray) expressionTb.isClass ------- - if (scope.isJavaLangObject(expressionTb)) { // potential runtime error - needRuntimeCheckcast = true; - return; - } - } else if ( - castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ - if (BlockScope.areTypesCompatible(expressionTb, castTb)) // no runtime error - return; - if (BlockScope.areTypesCompatible(castTb, expressionTb)) { - // potential runtime error - needRuntimeCheckcast = true; - return; - } - } else { // ----- (castTb.isInterface) expressionTb.isClass ------- - if (((ReferenceBinding) expressionTb).isFinal()) { - // no subclass for expressionTb, thus compile-time check is valid - if (BlockScope.areTypesCompatible(expressionTb, castTb)) - return; - } else { // a subclass may implement the interface ==> no check at compile time - needRuntimeCheckcast = true; - return; - } - } - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } - - // if (expressionTb.isInterface()) { cannot be anything else - if (castTb.isArrayType()) { - // ----- (castTb.isArray) expressionTb.isInterface ------ - if (scope.isJavaLangCloneable(expressionTb) - || scope.isJavaIoSerializable(expressionTb)) // potential runtime error - needRuntimeCheckcast = true; - else - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } else if ( - castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface -------- - if (scope.isJavaLangObject(castTb)) // no runtime error - return; - if (((ReferenceBinding) castTb).isFinal()) { - // no subclass for castTb, thus compile-time check is valid - if (!BlockScope.areTypesCompatible(castTb, expressionTb)) { - // potential runtime error - scope.problemReporter().typeCastError(this, castTb, expressionTb); - return; - } - } - } else { // ----- (castTb.isInterface) expressionTb.isInterface ------- - if (castTb != expressionTb - && (Scope.compareTypes(castTb, expressionTb) == NotRelated)) { - MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods(); - MethodBinding[] expressionTbMethods = - ((ReferenceBinding) expressionTb).methods(); - int exprMethodsLength = expressionTbMethods.length; - for (int i = 0, castMethodsLength = castTbMethods.length; - i < castMethodsLength; - i++) - for (int j = 0; j < exprMethodsLength; j++) - if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) - if (castTbMethods[i].selector == expressionTbMethods[j].selector) - if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) - scope.problemReporter().typeCastError(this, castTb, expressionTb); - } - } - needRuntimeCheckcast = true; - return; - } - - /** - * Cast expression code generation - * - * @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; - if (constant != NotAConstant) { - if (valueRequired - || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check - codeStream.generateConstant(constant, implicitConversion); - if (needRuntimeCheckcast) { - codeStream.checkcast(castTb); - if (!valueRequired) - codeStream.pop(); - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - expression.generateCode( - currentScope, - codeStream, - valueRequired || needRuntimeCheckcast); - if (needRuntimeCheckcast) { - codeStream.checkcast(castTb); - if (!valueRequired) - codeStream.pop(); - } else { - if (valueRequired) - codeStream.generateImplicitConversion(implicitConversion); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } - - public TypeBinding resolveType(BlockScope scope) { - // compute a new constant if the cast is effective - - // due to the fact an expression may start with ( and that a cast can also start with ( - // the field is an expression....it can be a TypeReference OR a NameReference Or - // any kind of Expression <-- this last one is invalid....... - - constant = Constant.NotAConstant; - implicitConversion = T_undefined; - TypeBinding expressionTb = expression.resolveType(scope); - if (expressionTb == null) - return null; - - if ((type instanceof TypeReference) || (type instanceof NameReference)) { - if ((castTb = type.resolveType(scope)) == null) - return null; - areTypesCastCompatible(scope, castTb, expressionTb); - return castTb; - } else { // expression as a cast !!!!!!!! - scope.problemReporter().invalidTypeReference(type); - return null; - } - } - - public String toStringExpression() { - - return "(" + type.toString(0) + ") " + //$NON-NLS-2$ //$NON-NLS-1$ - expression.toStringExpression(); - } - - public void traverse( - IAbstractSyntaxTreeVisitor visitor, - BlockScope blockScope) { - - if (visitor.visit(this, blockScope)) { - type.traverse(visitor, blockScope); - expression.traverse(visitor, blockScope); - } - visitor.endVisit(this, blockScope); - } -} \ No newline at end of file + /** The type in which we cast the expression. */ + public ConstantIdentifier type; + + /** The expression to be casted. */ + public Expression expression; + + /** + * Create a cast expression. + * @param type the type + * @param expression the expression + * @param sourceStart starting offset + * @param sourceEnd ending offset + */ + public CastExpression(final ConstantIdentifier type, + final Expression expression, + final int sourceStart, + final int sourceEnd) { + super(sourceStart, sourceEnd); + this.type = type; + this.expression = expression; + } + + /** + * Return the expression as String. + * @return the expression + */ + public String toStringExpression() { + final StringBuffer buff = new StringBuffer("("); + buff.append(type.toStringExpression()); + buff.append(") "); + buff.append(expression.toStringExpression()); + return buff.toString(); + } + + /** + * Get the variables from outside (parameters, globals ...) + */ + public void getOutsideVariable(final List list) { + } + + /** + * get the modified variables. + */ + public void getModifiedVariable(final List list) { + expression.getModifiedVariable(list); + } + + /** + * Get the variables used. + */ + public void getUsedVariable(final List list) { + expression.getUsedVariable(list); + } +}