### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/compiler/regression/AssertionTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AssertionTest.java,v retrieving revision 1.20 diff -u -r1.20 AssertionTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/AssertionTest.java 27 Jun 2008 16:04:45 -0000 1.20 +++ src/org/eclipse/jdt/core/tests/compiler/regression/AssertionTest.java 8 Dec 2008 16:52:19 -0000 @@ -440,4 +440,72 @@ true, // flush previous output dir content new String[] {"-da"}); } + //https://bugs.eclipse.org/bugs/show_bug.cgi?id=255008 + public void test017() { + runNegativeTest( + new String[] { /* test files */ + "X.java", + "public class X {\n" + + " protected void transform1(boolean srcPts) {\n" + + " final float error1;\n" + + " assert !(srcPts && (error1 = maxError()) > 0) : error1;\n" + + " }\n" + + " float foo1(boolean srcPts) {\n" + + " final float error2;\n" + + " if (!(srcPts && (error2 = maxError()) > 0)) {\n" + + " } else {\n" + + " return error2;\n" + + " }\n" + + " return 0;\n" + + " }\n" + + " float bar1(boolean srcPts) {\n" + + " final float error3;\n" + + " if ((srcPts && (error3 = maxError()) > 0)) {\n" + + " return error3;\n" + + " }\n" + + " return 0;\n" + + " } \n" + + " protected void transform2(boolean srcPts) {\n" + + " final float error4;\n" + + " assert (srcPts && (error4 = maxError()) > 0) : error4;\n" + + " }\n" + + " float foo2(boolean srcPts) {\n" + + " final float error5;\n" + + " if (srcPts && (error5 = maxError()) > 0) {\n" + + " } else {\n" + + " return error5;\n" + + " }\n" + + " return 0;\n" + + " }\n" + + " float bar2(boolean srcPts) {\n" + + " final float error6;\n" + + " if (!(srcPts && (error6 = maxError()) > 0)) {\n" + + " return error6;\n" + + " }\n" + + " return 0;\n" + + " }\n" + + " private float maxError() {\n" + + " return 0;\n" + + " }\n" + + "\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in X.java (at line 23)\n" + + " assert (srcPts && (error4 = maxError()) > 0) : error4;\n" + + " ^^^^^^\n" + + "The local variable error4 may not have been initialized\n" + + "----------\n" + + "2. ERROR in X.java (at line 29)\n" + + " return error5;\n" + + " ^^^^^^\n" + + "The local variable error5 may not have been initialized\n" + + "----------\n" + + "3. ERROR in X.java (at line 36)\n" + + " return error6;\n" + + " ^^^^^^\n" + + "The local variable error6 may not have been initialized\n" + + "----------\n"); + } + } #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java,v retrieving revision 1.57 diff -u -r1.57 AssertStatement.java --- compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java 24 Nov 2008 13:13:43 -0000 1.57 +++ compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java 8 Dec 2008 16:52:20 -0000 @@ -25,191 +25,173 @@ int preAssertInitStateIndex = -1; private FieldBinding assertionSyntheticFieldBinding; - public AssertStatement( - Expression exceptionArgument, - Expression assertExpression, - int startPosition) { - - this.assertExpression = assertExpression; - this.exceptionArgument = exceptionArgument; - this.sourceStart = startPosition; - this.sourceEnd = exceptionArgument.sourceEnd; - } - - public AssertStatement(Expression assertExpression, int startPosition) { - - this.assertExpression = assertExpression; - this.sourceStart = startPosition; - this.sourceEnd = assertExpression.sourceEnd; - } - - public FlowInfo analyseCode( - BlockScope currentScope, - FlowContext flowContext, - FlowInfo flowInfo) { - - this.preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); - - Constant cst = this.assertExpression.optimizedBooleanConstant(); - boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true; - boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false; - - FlowInfo assertRawInfo = this.assertExpression. - analyseCode(currentScope, flowContext, flowInfo.copy()); - UnconditionalFlowInfo assertWhenTrueInfo = assertRawInfo.initsWhenTrue(). - unconditionalInits(); - UnconditionalFlowInfo assertInfo = assertRawInfo.unconditionalCopy(); - if (isOptimizedTrueAssertion) { - assertInfo.setReachMode(FlowInfo.UNREACHABLE); - } +public AssertStatement( Expression exceptionArgument, Expression assertExpression, int startPosition) { + this.assertExpression = assertExpression; + this.exceptionArgument = exceptionArgument; + this.sourceStart = startPosition; + this.sourceEnd = exceptionArgument.sourceEnd; +} - if (this.exceptionArgument != null) { - // only gets evaluated when escaping - results are not taken into account - FlowInfo exceptionInfo = this.exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy()); +public AssertStatement(Expression assertExpression, int startPosition) { + this.assertExpression = assertExpression; + this.sourceStart = startPosition; + this.sourceEnd = assertExpression.sourceEnd; +} - if (isOptimizedTrueAssertion){ - currentScope.problemReporter().fakeReachable(this.exceptionArgument); - } else { - flowContext.checkExceptionHandlers( - currentScope.getJavaLangAssertionError(), - this, - exceptionInfo, - currentScope); - } - } +public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { + this.preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo); + + Constant cst = this.assertExpression.optimizedBooleanConstant(); + boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true; + boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false; + + FlowInfo conditionFlowInfo = this.assertExpression.analyseCode(currentScope, flowContext, flowInfo.copy()); + UnconditionalFlowInfo assertWhenTrueInfo = conditionFlowInfo.initsWhenTrue().unconditionalInits(); + FlowInfo assertInfo = conditionFlowInfo.initsWhenFalse(); + if (isOptimizedTrueAssertion) { + assertInfo.setReachMode(FlowInfo.UNREACHABLE); + } + + if (this.exceptionArgument != null) { + // only gets evaluated when escaping - results are not taken into account + FlowInfo exceptionInfo = this.exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy()); - if (!isOptimizedTrueAssertion){ - // add the assert support in the clinit - manageSyntheticAccessIfNecessary(currentScope, flowInfo); - } - if (isOptimizedFalseAssertion) { - return flowInfo; // if assertions are enabled, the following code will be unreachable - // change this if we need to carry null analysis results of the assert - // expression downstream + if (isOptimizedTrueAssertion){ + currentScope.problemReporter().fakeReachable(this.exceptionArgument); } else { - return flowInfo.mergedWith(assertInfo.nullInfoLessUnconditionalCopy()). - addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo()); - // keep the merge from the initial code for the definite assignment - // analysis, tweak the null part to influence nulls downstream + flowContext.checkExceptionHandlers( + currentScope.getJavaLangAssertionError(), + this, + exceptionInfo, + currentScope); } } - public void generateCode(BlockScope currentScope, CodeStream codeStream) { - - if ((this.bits & IsReachable) == 0) { - return; - } - int pc = codeStream.position; - - if (this.assertionSyntheticFieldBinding != null) { - BranchLabel assertionActivationLabel = new BranchLabel(codeStream); - codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */); - codeStream.ifne(assertionActivationLabel); - - BranchLabel falseLabel; - this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null , true); - codeStream.newJavaLangAssertionError(); - codeStream.dup(); - if (this.exceptionArgument != null) { - this.exceptionArgument.generateCode(currentScope, codeStream, true); - codeStream.invokeJavaLangAssertionErrorConstructor(this.exceptionArgument.implicitConversion & 0xF); - } else { - codeStream.invokeJavaLangAssertionErrorDefaultConstructor(); - } - codeStream.athrow(); + if (!isOptimizedTrueAssertion){ + // add the assert support in the clinit + manageSyntheticAccessIfNecessary(currentScope, flowInfo); + } + if (isOptimizedFalseAssertion) { + return flowInfo; // if assertions are enabled, the following code will be unreachable + // change this if we need to carry null analysis results of the assert + // expression downstream + } else { + return flowInfo.mergedWith(assertInfo.nullInfoLessUnconditionalCopy()). + addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo()); + // keep the merge from the initial code for the definite assignment + // analysis, tweak the null part to influence nulls downstream + } +} - // May loose some local variable initializations : affecting the local variable attributes - if (this.preAssertInitStateIndex != -1) { - codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex); - } - falseLabel.place(); - assertionActivationLabel.place(); +public void generateCode(BlockScope currentScope, CodeStream codeStream) { + if ((this.bits & IsReachable) == 0) { + return; + } + int pc = codeStream.position; + + if (this.assertionSyntheticFieldBinding != null) { + BranchLabel assertionActivationLabel = new BranchLabel(codeStream); + codeStream.fieldAccess(Opcodes.OPC_getstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */); + codeStream.ifne(assertionActivationLabel); + + BranchLabel falseLabel; + this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null , true); + codeStream.newJavaLangAssertionError(); + codeStream.dup(); + if (this.exceptionArgument != null) { + this.exceptionArgument.generateCode(currentScope, codeStream, true); + codeStream.invokeJavaLangAssertionErrorConstructor(this.exceptionArgument.implicitConversion & 0xF); } else { - // May loose some local variable initializations : affecting the local variable attributes - if (this.preAssertInitStateIndex != -1) { - codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex); - } + codeStream.invokeJavaLangAssertionErrorDefaultConstructor(); } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } + codeStream.athrow(); - public void resolve(BlockScope scope) { - this.assertExpression.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); - if (this.exceptionArgument != null) { - TypeBinding exceptionArgumentType = this.exceptionArgument.resolveType(scope); - if (exceptionArgumentType != null){ - int id = exceptionArgumentType.id; - switch(id) { - case T_void : - scope.problemReporter().illegalVoidExpression(this.exceptionArgument); - //$FALL-THROUGH$ - default: - id = T_JavaLangObject; - //$FALL-THROUGH$ - case T_boolean : - case T_byte : - case T_char : - case T_short : - case T_double : - case T_float : - case T_int : - case T_long : - case T_JavaLangString : - this.exceptionArgument.implicitConversion = (id << 4) + id; - } - } + // May loose some local variable initializations : affecting the local variable attributes + if (this.preAssertInitStateIndex != -1) { + codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex); + } + falseLabel.place(); + assertionActivationLabel.place(); + } else { + // May loose some local variable initializations : affecting the local variable attributes + if (this.preAssertInitStateIndex != -1) { + codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex); } } + codeStream.recordPositionsFrom(pc, this.sourceStart); +} - public void traverse(ASTVisitor visitor, BlockScope scope) { - - if (visitor.visit(this, scope)) { - this.assertExpression.traverse(visitor, scope); - if (this.exceptionArgument != null) { - this.exceptionArgument.traverse(visitor, scope); +public void resolve(BlockScope scope) { + this.assertExpression.resolveTypeExpecting(scope, TypeBinding.BOOLEAN); + if (this.exceptionArgument != null) { + TypeBinding exceptionArgumentType = this.exceptionArgument.resolveType(scope); + if (exceptionArgumentType != null){ + int id = exceptionArgumentType.id; + switch(id) { + case T_void : + scope.problemReporter().illegalVoidExpression(this.exceptionArgument); + //$FALL-THROUGH$ + default: + id = T_JavaLangObject; + //$FALL-THROUGH$ + case T_boolean : + case T_byte : + case T_char : + case T_short : + case T_double : + case T_float : + case T_int : + case T_long : + case T_JavaLangString : + this.exceptionArgument.implicitConversion = (id << 4) + id; } } - visitor.endVisit(this, scope); } +} - public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { - - if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { - - // need assertion flag: $assertionsDisabled on outer most source clas - // (in case of static member of interface, will use the outermost static member - bug 22334) - SourceTypeBinding outerMostClass = currentScope.enclosingSourceType(); - while (outerMostClass.isLocalType()) { - ReferenceBinding enclosing = outerMostClass.enclosingType(); - if (enclosing == null || enclosing.isInterface()) break; - outerMostClass = (SourceTypeBinding) enclosing; - } - - this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope); - - // find and enable assertion support - TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType(); - AbstractMethodDeclaration[] methods = typeDeclaration.methods; - for (int i = 0, max = methods.length; i < max; i++) { - AbstractMethodDeclaration method = methods[i]; - if (method.isClinit()) { - ((Clinit) method).setAssertionSupport(this.assertionSyntheticFieldBinding, currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5); - break; - } - } +public void traverse(ASTVisitor visitor, BlockScope scope) { + if (visitor.visit(this, scope)) { + this.assertExpression.traverse(visitor, scope); + if (this.exceptionArgument != null) { + this.exceptionArgument.traverse(visitor, scope); } } + visitor.endVisit(this, scope); +} - public StringBuffer printStatement(int tab, StringBuffer output) { - - printIndent(tab, output); - output.append("assert "); //$NON-NLS-1$ - this.assertExpression.printExpression(0, output); - if (this.exceptionArgument != null) { - output.append(": "); //$NON-NLS-1$ - this.exceptionArgument.printExpression(0, output); +public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { + if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { + // need assertion flag: $assertionsDisabled on outer most source clas + // (in case of static member of interface, will use the outermost static member - bug 22334) + SourceTypeBinding outerMostClass = currentScope.enclosingSourceType(); + while (outerMostClass.isLocalType()) { + ReferenceBinding enclosing = outerMostClass.enclosingType(); + if (enclosing == null || enclosing.isInterface()) break; + outerMostClass = (SourceTypeBinding) enclosing; + } + this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope); + + // find and enable assertion support + TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType(); + AbstractMethodDeclaration[] methods = typeDeclaration.methods; + for (int i = 0, max = methods.length; i < max; i++) { + AbstractMethodDeclaration method = methods[i]; + if (method.isClinit()) { + ((Clinit) method).setAssertionSupport(this.assertionSyntheticFieldBinding, currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5); + break; + } } - return output.append(';'); } +} +public StringBuffer printStatement(int tab, StringBuffer output) { + printIndent(tab, output); + output.append("assert "); //$NON-NLS-1$ + this.assertExpression.printExpression(0, output); + if (this.exceptionArgument != null) { + output.append(": "); //$NON-NLS-1$ + this.exceptionArgument.printExpression(0, output); + } + return output.append(';'); +} }