2362N/A * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * WARNING: The contents of this source file are not part of any 0N/A * supported API. Code that depends on them does so at its own risk: 0N/A * they are subject to change or removal without notice. 0N/A// * Constructor for try (init) {body} 0N/A// public FinallyStatement(long where, Statement init, Statement body, int junk) { 0N/A// this(where, body, null); 0N/A // Handle the proposed 'try (init) { stmts } finally { stmts }' syntax. 0N/A // This feature has not been adopted, and support is presently disabled. 0N/A /*-----------------------------------------------------------* 0N/A ClassDefinition sourceClass = ctx.field.getClassDefinition(); 0N/A Expression tryExpr = null; 0N/A DeclarationStatement tryDecl = null; 0N/A long where = init.getWhere(); 0N/A // find out whether init is a simple expression or a declaration 0N/A if (init.getOp() == EXPRESSION) { 0N/A tryExpr = ((ExpressionStatement)init).expr; 0N/A init = null; // restore it below 0N/A vset = tryExpr.checkValue(env, ctx, vset, exp); 0N/A } else if (init.getOp() == DECLARATION) { 0N/A tryDecl = (DeclarationStatement) init; 0N/A init = null; // restore it below 0N/A vset = tryDecl.checkBlockStatement(env, ctx, vset, exp); 0N/A if (tryDecl.args.length != 1) { 0N/A env.error(where, "invalid.decl"); 0N/A ((VarDeclarationStatement) tryDecl.args[0]).field; 0N/A tryExpr = new IdentifierExpression(where, field); 0N/A tryExpr.type = field.getType(); 0N/A env.error(where, "invalid.expr"); 0N/A vset = init.check(env, ctx, vset, exp); 0N/A Type type = (tryExpr == null) ? Type.tError : tryExpr.getType(); 0N/A MemberDefinition tryEnter = null; 0N/A MemberDefinition tryExit = null; 0N/A if (!type.isType(TC_CLASS)) { 0N/A if (!type.isType(TC_ERROR)) { 0N/A env.error(where, "invalid.method.invoke", type); 0N/A Identifier idTryEnter = Identifier.lookup("tryEnter"); 0N/A Identifier idTryExit = Identifier.lookup("tryExit"); 0N/A Type tTryMethod = Type.tMethod(Type.tVoid); 0N/A ClassDefinition tryClass = env.getClassDefinition(type); 0N/A tryEnter = tryClass.matchMethod(env, sourceClass, idTryEnter); 0N/A tryExit = tryClass.matchMethod(env, sourceClass, idTryExit); 0N/A if (tryEnter != null && !tryEnter.getType().equals(tTryMethod)) { 0N/A if (tryExit != null && !tryExit.getType().equals(tTryMethod)) { 0N/A } catch (ClassNotFound ee) { 0N/A env.error(where, "class.not.found", ee.name, ctx.field); 0N/A } catch (AmbiguousMember ee) { 0N/A Identifier id = ee.field1.getName(); 0N/A env.error(where, "ambig.field", id, ee.field1, ee.field2); 0N/A if (tryEnter == null || tryExit == null) { 0N/A // Make a better (more didactic) error here! 0N/A env.error(where, "invalid.method.invoke", type); 0N/A tryTemp = new LocalMember(where, sourceClass, 0, 0N/A type, Identifier.lookup("<try_object>")); 0N/A ctx = new Context(ctx, this); 0N/A ctx.declare(env, tryTemp); 0N/A e = new IdentifierExpression(where, tryTemp); 0N/A e = new AssignExpression(where, e, tryExpr); 0N/A e = new MethodExpression(where, e, tryEnter, new Expression[0]); 0N/A e.type = Type.tVoid; 0N/A Statement enterCall = new ExpressionStatement(where, e); 0N/A // store it on the init, for code generation 0N/A if (tryDecl != null) { 0N/A Statement args2[] = { tryDecl.args[0], enterCall }; 0N/A tryDecl.args = args2; 0N/A e = new IdentifierExpression(where, tryTemp); 0N/A e = new MethodExpression(where, e, tryExit, new Expression[0]); 0N/A e.type = Type.tVoid; 0N/A Statement exitCall = new ExpressionStatement(where, e); 0N/A finalbody = exitCall; 0N/A *-----------------------------------------------------------*/ 0N/A // Check the try part. We reach the end of the try part either by 0N/A // finishing normally, or doing a break to the label of the try/finally. 0N/A // NOTE: I don't think newctx1.vsBreak is ever used -- see TryStatement. 0N/A // Check the finally part. 0N/A // Should never access this field. The null indicates the finally part. 0N/A // If !finallyCanFinish, then the only possible exceptions that can 0N/A // occur at this point are the ones preceding the try/finally, or 0N/A // the ones generated by the finally. Anything in the try is 0N/A // irrelevant. Otherwise, we have to merge in all the exceptions 0N/A // generated by the body into exp. 0N/A // Add newexp's back into exp; cf. ThrowStatement.check(). 0N/A * Create a copy of the statement for method inlining 0N/A * Compute cost of inlining this statement 0N/A // allocate space for the exception and return address 0N/A // Cleanup afer body 0N/A // just goto the cleanup code. It will never return. 0N/A // pop exception off stack. Fall through to finally code 0N/A // The finally part, which is marked by the contLabel. Update 0N/A // breakLabel: since break's in the finally are different 0N/A // contLabel: to null to indicate no longer in the protected code.