1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
13 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
14 import org.eclipse.jdt.internal.compiler.codegen.*;
15 import org.eclipse.jdt.internal.compiler.flow.*;
16 import org.eclipse.jdt.internal.compiler.impl.Constant;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18 import org.eclipse.jdt.internal.compiler.ASTVisitor;
20 public class AssertStatement extends Statement {
22 public Expression assertExpression, exceptionArgument;
24 // for local variable attribute
25 int preAssertInitStateIndex = -1;
26 private FieldBinding assertionSyntheticFieldBinding;
28 public AssertStatement(
29 Expression exceptionArgument,
30 Expression assertExpression,
33 this.assertExpression = assertExpression;
34 this.exceptionArgument = exceptionArgument;
35 sourceStart = startPosition;
36 sourceEnd = exceptionArgument.sourceEnd;
39 public AssertStatement(Expression assertExpression, int startPosition) {
41 this.assertExpression = assertExpression;
42 sourceStart = startPosition;
43 sourceEnd = assertExpression.sourceEnd;
46 public FlowInfo analyseCode(
47 BlockScope currentScope,
48 FlowContext flowContext,
51 preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
53 Constant cst = this.assertExpression.optimizedBooleanConstant();
54 boolean isOptimizedTrueAssertion = cst != NotAConstant && cst.booleanValue() == true;
55 boolean isOptimizedFalseAssertion = cst != NotAConstant && cst.booleanValue() == false;
57 FlowInfo assertInfo = flowInfo.copy();
58 if (isOptimizedTrueAssertion) {
59 assertInfo.setReachMode(FlowInfo.UNREACHABLE);
61 assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
63 if (exceptionArgument != null) {
64 // only gets evaluated when escaping - results are not taken into account
65 FlowInfo exceptionInfo = exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy());
67 if (!isOptimizedTrueAssertion){
68 flowContext.checkExceptionHandlers(
69 currentScope.getJavaLangAssertionError(),
76 if (!isOptimizedTrueAssertion){
77 // add the assert support in the clinit
78 manageSyntheticAccessIfNecessary(currentScope, flowInfo);
80 if (isOptimizedFalseAssertion) {
81 return flowInfo; // if assertions are enabled, the following code will be unreachable
83 return flowInfo.mergedWith(assertInfo.unconditionalInits());
87 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
89 if ((bits & IsReachableMASK) == 0) {
92 int pc = codeStream.position;
94 if (this.assertionSyntheticFieldBinding != null) {
95 Label assertionActivationLabel = new Label(codeStream);
96 codeStream.getstatic(this.assertionSyntheticFieldBinding);
97 codeStream.ifne(assertionActivationLabel);
99 Label falseLabel = new Label(codeStream);
100 this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new Label(codeStream)), null , true);
101 codeStream.newJavaLangAssertionError();
103 if (exceptionArgument != null) {
104 exceptionArgument.generateCode(currentScope, codeStream, true);
105 codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF);
107 codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
111 assertionActivationLabel.place();
114 // May loose some local variable initializations : affecting the local variable attributes
115 if (preAssertInitStateIndex != -1) {
116 codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex);
118 codeStream.recordPositionsFrom(pc, this.sourceStart);
121 public void resolve(BlockScope scope) {
123 assertExpression.resolveTypeExpecting(scope, BooleanBinding);
124 if (exceptionArgument != null) {
125 TypeBinding exceptionArgumentType = exceptionArgument.resolveType(scope);
126 if (exceptionArgumentType != null){
127 int id = exceptionArgumentType.id;
130 scope.problemReporter().illegalVoidExpression(exceptionArgument);
132 id = T_JavaLangObject;
141 case T_JavaLangString :
142 exceptionArgument.implicitConversion = (id << 4) + id;
148 public void traverse(ASTVisitor visitor, BlockScope scope) {
150 if (visitor.visit(this, scope)) {
151 assertExpression.traverse(visitor, scope);
152 if (exceptionArgument != null) {
153 exceptionArgument.traverse(visitor, scope);
156 visitor.endVisit(this, scope);
159 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
161 if (!flowInfo.isReachable()) return;
163 // need assertion flag: $assertionsDisabled on outer most source clas
164 // (in case of static member of interface, will use the outermost static member - bug 22334)
165 SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
166 while (outerMostClass.isLocalType()){
167 ReferenceBinding enclosing = outerMostClass.enclosingType();
168 if (enclosing == null || enclosing.isInterface()) break;
169 outerMostClass = (SourceTypeBinding) enclosing;
172 this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);
174 // find <clinit> and enable assertion support
175 TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
176 AbstractMethodDeclaration[] methods = typeDeclaration.methods;
177 for (int i = 0, max = methods.length; i < max; i++) {
178 AbstractMethodDeclaration method = methods[i];
179 if (method.isClinit()) {
180 ((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding, currentScope.environment().options.sourceLevel < ClassFileConstants.JDK1_5);
186 public StringBuffer printStatement(int tab, StringBuffer output) {
188 printIndent(tab, output);
189 output.append("assert "); //$NON-NLS-1$
190 this.assertExpression.printExpression(0, output);
191 if (this.exceptionArgument != null) {
192 output.append(": "); //$NON-NLS-1$
193 this.exceptionArgument.printExpression(0, output);
195 return output.append(';');