X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fast%2FCastExpression.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fast%2FCastExpression.java;h=0000000000000000000000000000000000000000;hb=6f0cd02d46e011bd5599e1b7fefc6159cb811135;hp=ecfe767b9e1b17c427efe70f8de11b5414d92865;hpb=622d0e5a4b1b35b6918a516a79a0cc22272a919e;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java deleted file mode 100644 index ecfe767..0000000 --- a/src/org/eclipse/jdt/internal/compiler/ast/CastExpression.java +++ /dev/null @@ -1,512 +0,0 @@ -/******************************************************************************* - * 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 - * Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752) - *******************************************************************************/ -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.impl.*; -import org.eclipse.jdt.internal.compiler.codegen.*; -import org.eclipse.jdt.internal.compiler.flow.*; -import org.eclipse.jdt.internal.compiler.lookup.*; -import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; - -public class CastExpression extends Expression { - - public Expression expression; - public Expression type; - - //expression.implicitConversion holds the cast for baseType casting - public CastExpression(Expression expression, Expression type) { - this.expression = expression; - this.type = type; - - //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(); - } - - /** - * Returns false if the cast is unnecessary - */ - public final boolean checkCastTypesCompatibility( - 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. - - if (castType == null || expressionType == null) return true; - - // 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 false; - } - boolean necessary = false; - if (expressionType.isCompatibleWith(castType) - || (necessary = 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 necessary; - - } - } - scope.problemReporter().typeCastError(this, castType, expressionType); - 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().typeCastError(this, castType, expressionType); - 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) { - this.bits |= NeedRuntimeCheckCastMASK; - } else { - scope.problemReporter().typeCastError(this, castType, expressionType); - } - 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) { - this.bits |= NeedRuntimeCheckCastMASK; - return true; - } - } - scope.problemReporter().typeCastError(this, castType, expressionType); - return true; - } - - if (expressionType.isClass()) { - if (castType.isArrayType()) { - // ---- (castType.isArray) expressionType.isClass ------- - if (expressionType.id == T_Object) { // potential runtime error - this.bits |= NeedRuntimeCheckCastMASK; - return true; - } - } 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 false; - } - if (castType.isCompatibleWith(expressionType)) { - // potential runtime error - this.bits |= NeedRuntimeCheckCastMASK; - 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 - this.bits |= NeedRuntimeCheckCastMASK; - return true; - } - // no subclass for expressionType, thus compile-time check is valid - } - scope.problemReporter().typeCastError(this, castType, expressionType); - 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 - this.bits |= NeedRuntimeCheckCastMASK; - } else { - scope.problemReporter().typeCastError(this, castType, expressionType); - } - 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().typeCastError(this, castType, expressionType); - 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().typeCastError(this, castType, expressionType); - } - } - } - } - this.bits |= NeedRuntimeCheckCastMASK; - return true; - } - - /** - * Casting an enclosing instance will considered as useful if removing it would actually bind to a different type - */ - public static void checkNeedForEnclosingInstanceCast(BlockScope scope, Expression enclosingInstance, TypeBinding enclosingInstanceType, TypeBinding memberType) { - - if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; - - TypeBinding castedExpressionType = ((CastExpression)enclosingInstance).expression.resolvedType; - if (castedExpressionType == null) return; // cannot do better - // obvious identity cast - if (castedExpressionType == enclosingInstanceType) { - scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance); - } else if (castedExpressionType == NullBinding){ - return; // tolerate null enclosing instance cast - } else { - TypeBinding alternateEnclosingInstanceType = castedExpressionType; - if (castedExpressionType.isBaseType() || castedExpressionType.isArrayType()) return; // error case - if (memberType == scope.getMemberType(memberType.sourceName(), (ReferenceBinding) alternateEnclosingInstanceType)) { - scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance); - } - } - } - - /** - * Only complain for identity cast, since other type of casts may be useful: e.g. ~((~(long) 0) << 32) is different from: ~((~0) << 32) - */ - public static void checkNeedForArgumentCast(BlockScope scope, int operator, int operatorSignature, Expression expression, int expressionTypeId) { - - if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; - - // check need for left operand cast - int alternateLeftTypeId = expressionTypeId; - if ((expression.bits & UnnecessaryCastMask) == 0 && expression.resolvedType.isBaseType()) { - // narrowing conversion on base type may change value, thus necessary - return; - } else { - TypeBinding alternateLeftType = ((CastExpression)expression).expression.resolvedType; - if (alternateLeftType == null) return; // cannot do better - if ((alternateLeftTypeId = alternateLeftType.id) == expressionTypeId) { // obvious identity cast - scope.problemReporter().unnecessaryCast((CastExpression)expression); - return; - } else if (alternateLeftTypeId == T_null) { - alternateLeftTypeId = expressionTypeId; // tolerate null argument cast - return; - } - } -/* tolerate widening cast in unary expressions, as may be used when combined in binary expressions (41680) - int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateLeftTypeId]; - // (cast) left Op (cast) right --> result - // 1111 0000 1111 0000 1111 - // <<16 <<12 <<8 <<4 <<0 - final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types - if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result - scope.problemReporter().unnecessaryCastForArgument((CastExpression)expression, TypeBinding.wellKnownType(scope, expression.implicitConversion >> 4)); - } -*/ - } - - /** - * Cast expressions will considered as useful if removing them all would actually bind to a different method - * (no fine grain analysis on per casted argument basis, simply separate widening cast from narrowing ones) - */ - public static void checkNeedForArgumentCasts(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] argumentTypes, final InvocationSite invocationSite) { - - if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; - - int length = argumentTypes.length; - - // iterate over arguments, and retrieve original argument types (before cast) - TypeBinding[] rawArgumentTypes = argumentTypes; - for (int i = 0; i < length; i++) { - Expression argument = arguments[i]; - if (argument instanceof CastExpression) { - // narrowing conversion on base type may change value, thus necessary - if ((argument.bits & UnnecessaryCastMask) == 0 && argument.resolvedType.isBaseType()) { - continue; - } - TypeBinding castedExpressionType = ((CastExpression)argument).expression.resolvedType; - if (castedExpressionType == null) return; // cannot do better - // obvious identity cast - if (castedExpressionType == argumentTypes[i]) { - scope.problemReporter().unnecessaryCast((CastExpression)argument); - } else if (castedExpressionType == NullBinding){ - continue; // tolerate null argument cast - } else { - if (rawArgumentTypes == argumentTypes) { - System.arraycopy(rawArgumentTypes, 0, rawArgumentTypes = new TypeBinding[length], 0, length); - } - // retain original argument type - rawArgumentTypes[i] = castedExpressionType; - } - } - } - // perform alternate lookup with original types - if (rawArgumentTypes != argumentTypes) { - checkAlternateBinding(scope, receiver, receiverType, binding, arguments, argumentTypes, rawArgumentTypes, invocationSite); - } - } - - /** - * Check binary operator casted arguments - */ - public static void checkNeedForArgumentCasts(BlockScope scope, int operator, int operatorSignature, Expression left, int leftTypeId, boolean leftIsCast, Expression right, int rightTypeId, boolean rightIsCast) { - - if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return; - - // check need for left operand cast - int alternateLeftTypeId = leftTypeId; - if (leftIsCast) { - if ((left.bits & UnnecessaryCastMask) == 0 && left.resolvedType.isBaseType()) { - // narrowing conversion on base type may change value, thus necessary - leftIsCast = false; - } else { - TypeBinding alternateLeftType = ((CastExpression)left).expression.resolvedType; - if (alternateLeftType == null) return; // cannot do better - if ((alternateLeftTypeId = alternateLeftType.id) == leftTypeId) { // obvious identity cast - scope.problemReporter().unnecessaryCast((CastExpression)left); - leftIsCast = false; - } else if (alternateLeftTypeId == T_null) { - alternateLeftTypeId = leftTypeId; // tolerate null argument cast - leftIsCast = false; - } - } - } - // check need for right operand cast - int alternateRightTypeId = rightTypeId; - if (rightIsCast) { - if ((right.bits & UnnecessaryCastMask) == 0 && right.resolvedType.isBaseType()) { - // narrowing conversion on base type may change value, thus necessary - rightIsCast = false; - } else { - TypeBinding alternateRightType = ((CastExpression)right).expression.resolvedType; - if (alternateRightType == null) return; // cannot do better - if ((alternateRightTypeId = alternateRightType.id) == rightTypeId) { // obvious identity cast - scope.problemReporter().unnecessaryCast((CastExpression)right); - rightIsCast = false; - } else if (alternateRightTypeId == T_null) { - alternateRightTypeId = rightTypeId; // tolerate null argument cast - rightIsCast = false; - } - } - } - if (leftIsCast || rightIsCast) { - if (alternateLeftTypeId > 15 || alternateRightTypeId > 15) { // must convert String + Object || Object + String - if (alternateLeftTypeId == T_String) { - alternateRightTypeId = T_Object; - } else if (alternateRightTypeId == T_String) { - alternateLeftTypeId = T_Object; - } else { - return; // invalid operator - } - } - int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateRightTypeId]; - // (cast) left Op (cast) right --> result - // 1111 0000 1111 0000 1111 - // <<16 <<12 <<8 <<4 <<0 - final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types - if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result - if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left, TypeBinding.wellKnownType(scope, left.implicitConversion >> 4)); - if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope, right.implicitConversion >> 4)); - } - } - } - - private static void checkAlternateBinding(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] originalArgumentTypes, TypeBinding[] alternateArgumentTypes, final InvocationSite invocationSite) { - - InvocationSite fakeInvocationSite = new InvocationSite(){ - public boolean isSuperAccess(){ return invocationSite.isSuperAccess(); } - public boolean isTypeAccess() { return invocationSite.isTypeAccess(); } - public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */} - public void setDepth(int depth) { /* ignore */} - public void setFieldIndex(int depth){ /* ignore */} - public int sourceStart() { return 0; } - public int sourceEnd() { return 0; } - }; - MethodBinding bindingIfNoCast; - if (binding.isConstructor()) { - bindingIfNoCast = scope.getConstructor((ReferenceBinding)receiverType, alternateArgumentTypes, fakeInvocationSite); - } else { - bindingIfNoCast = receiver.isImplicitThis() - ? scope.getImplicitMethod(binding.selector, alternateArgumentTypes, fakeInvocationSite) - : scope.getMethod(receiverType, binding.selector, alternateArgumentTypes, fakeInvocationSite); - } - if (bindingIfNoCast == binding) { - for (int i = 0, length = originalArgumentTypes.length; i < length; i++) { - if (originalArgumentTypes[i] != alternateArgumentTypes[i]) { - scope.problemReporter().unnecessaryCastForArgument((CastExpression)arguments[i], binding.parameters[i]); - } - } - } - } - /** - * 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; - boolean needRuntimeCheckcast = (this.bits & NeedRuntimeCheckCastMASK) != 0; - 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) - && ((type.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // no extra parenthesis around type: ((A))exp - - this.resolvedType = type.resolveType(scope); - TypeBinding expressionType = expression.resolveType(scope); - if (this.resolvedType != null && expressionType != null) { - boolean necessary = checkCastTypesCompatibility(scope, this.resolvedType, expressionType); - if (!necessary && this.expression.resolvedType != null) { // cannot do better if expression is not bound - this.bits |= UnnecessaryCastMask; - if ((this.bits & IgnoreNeedForCastCheckMASK) == 0) { - scope.problemReporter().unnecessaryCast(this); - } - } - } - return this.resolvedType; - } else { // expression as a cast !!!!!!!! - TypeBinding expressionType = expression.resolveType(scope); - if (expressionType == null) return null; - scope.problemReporter().invalidTypeReference(type); - return null; - } - } - - public void traverse( - ASTVisitor visitor, - BlockScope blockScope) { - - if (visitor.visit(this, blockScope)) { - type.traverse(visitor, blockScope); - expression.traverse(visitor, blockScope); - } - visitor.endVisit(this, blockScope); - } -}