+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2000, 2003 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 net.sourceforge.phpeclipse.internal.compiler.ast;
-
-import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
-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;
-
-public class CastExpression extends Expression {
-
- public Expression expression;
- public Expression type;
- public boolean needRuntimeCheckcast;
-
- //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 castType,
- TypeBinding expressionType) {
-
- // see specifications 5.5
- // 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 (castType == null || expressionType == null) return;
-
- // identity conversion cannot be performed upfront, due to side-effects
- // like constant propagation
-
- if (castType.isBaseType()) {
- if (expressionType.isBaseType()) {
- if (expressionType == castType) {
- expression.implicitWidening(castType, expressionType);
- constant = expression.constant; //use the same constant
- return;
- }
- if (expressionType.isCompatibleWith(castType)
- || BaseTypeBinding.isNarrowing(castType.id, expressionType.id)) {
- expression.implicitConversion = (castType.id << 4) + expressionType.id;
- if (expression.constant != Constant.NotAConstant)
- constant = expression.constant.castTo(expression.implicitConversion);
- return;
- }
- }
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- }
-
- //-----------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; //null is compatible with every thing
- }
- if (expressionType.isBaseType()) {
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- }
-
- if (expressionType.isArrayType()) {
- if (castType == expressionType) return; // 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)
- needRuntimeCheckcast = true;
- else
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- }
- // recursively on the elements...
- areTypesCastCompatible(
- scope,
- ((ArrayBinding) castType).elementsType(scope),
- exprElementType);
- return;
- } else if (
- castType.isClass()) {
- //------(castType.isClass) expressionType.isArray ---------------
- if (scope.isJavaLangObject(castType))
- return;
- } else { //------- (castType.isInterface) expressionType.isArray -----------
- if (scope.isJavaLangCloneable(castType) || scope.isJavaIoSerializable(castType)) {
- needRuntimeCheckcast = true;
- return;
- }
- }
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- }
-
- if (expressionType.isClass()) {
- if (castType.isArrayType()) {
- // ---- (castType.isArray) expressionType.isClass -------
- if (scope.isJavaLangObject(expressionType)) { // potential runtime error
- needRuntimeCheckcast = true;
- return;
- }
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
- if (expressionType.isCompatibleWith(castType)){ // no runtime error
- if (castType.id == T_String) constant = expression.constant; // (String) cst is still a constant
- return;
- }
- if (castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- needRuntimeCheckcast = true;
- return;
- }
- } else { // ----- (castType.isInterface) expressionType.isClass -------
- if (((ReferenceBinding) expressionType).isFinal()) {
- // no subclass for expressionType, thus compile-time check is valid
- if (expressionType.isCompatibleWith(castType))
- return;
- } else { // a subclass may implement the interface ==> no check at compile time
- needRuntimeCheckcast = true;
- return;
- }
- }
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- }
-
- // if (expressionType.isInterface()) { cannot be anything else
- if (castType.isArrayType()) {
- // ----- (castType.isArray) expressionType.isInterface ------
- if (scope.isJavaLangCloneable(expressionType)
- || scope.isJavaIoSerializable(expressionType)) // potential runtime error
- needRuntimeCheckcast = true;
- else
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- } else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
- if (scope.isJavaLangObject(castType)) // no runtime error
- return;
- if (((ReferenceBinding) castType).isFinal()) {
- // no subclass for castType, thus compile-time check is valid
- if (!castType.isCompatibleWith(expressionType)) {
- // potential runtime error
- scope.problemReporter().typeCastError(this, castType, expressionType);
- return;
- }
- }
- } else { // ----- (castType.isInterface) expressionType.isInterface -------
- if (castType == expressionType) return; // identity conversion
- if (Scope.compareTypes(castType, expressionType) == NotRelated) {
- 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)
- && (castTypeMethods[i].selector == expressionTypeMethods[j].selector)
- && castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
- scope.problemReporter().typeCastError(this, castType, expressionType);
- }
- }
- }
- }
- needRuntimeCheckcast = true;
- return;
- }
-
- /**
- * Cast expression code generation
- *
- * @param currentScope net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
- * @param codeStream net.sourceforge.phpdt.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(this.resolvedType);
-// if (!valueRequired)
-// codeStream.pop();
-// }
-// }
-// codeStream.recordPositionsFrom(pc, this.sourceStart);
-// return;
-// }
-// expression.generateCode(
-// currentScope,
-// codeStream,
-// valueRequired || needRuntimeCheckcast);
-// if (needRuntimeCheckcast) {
-// codeStream.checkcast(this.resolvedType);
-// if (!valueRequired)
-// codeStream.pop();
-// } else {
-// if (valueRequired)
-// codeStream.generateImplicitConversion(implicitConversion);
-// }
-// codeStream.recordPositionsFrom(pc, this.sourceStart);
-// }
-
- public Expression innermostCastedExpression(){
- Expression current = this.expression;
- while (current instanceof CastExpression) {
- current = ((CastExpression) current).expression;
- }
- return current;
- }
- public StringBuffer printExpression(int indent, StringBuffer output) {
-
- output.append('(');
- type.print(0, output).append(") "); //$NON-NLS-1$
- return expression.printExpression(0, output);
- }
-
- 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;
- if ((type instanceof TypeReference) || (type instanceof NameReference)) {
- this.resolvedType = type.resolveType(scope);
- TypeBinding castedExpressionType = expression.resolveType(scope);
- if (this.resolvedType != null && castedExpressionType != null) {
- areTypesCastCompatible(scope, this.resolvedType, castedExpressionType);
- }
- return this.resolvedType;
- } else { // expression as a cast !!!!!!!!
- TypeBinding castedExpressionType = expression.resolveType(scope);
- if (castedExpressionType == null) return null;
- scope.problemReporter().invalidTypeReference(type);
- return null;
- }
- }
-
- public String toStringExpression() {
-
- return "(" + type.toString(0) + ") " + //$NON-NLS-2$ //$NON-NLS-1$
- expression.toStringExpression();
- }
-
- public void traverse(
- ASTVisitor visitor,
- BlockScope blockScope) {
-
- if (visitor.visit(this, blockScope)) {
- type.traverse(visitor, blockScope);
- expression.traverse(visitor, blockScope);
- }
- visitor.endVisit(this, blockScope);
- }
-}