totally new file layout
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / CastExpression.java
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 (file)
index ecfe767..0000000
+++ /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);
-       }
-}