001: /*
002: * Copyright 1994-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.tools.tree;
027:
028: import sun.tools.java.*;
029: import sun.tools.asm.Assembler;
030: import sun.tools.asm.Label;
031: import java.io.PrintStream;
032: import java.util.Hashtable;
033:
034: /**
035: * WARNING: The contents of this source file are not part of any
036: * supported API. Code that depends on them does so at its own risk:
037: * they are subject to change or removal without notice.
038: */
039: public class ReturnStatement extends Statement {
040: Expression expr;
041:
042: /**
043: * Constructor
044: */
045: public ReturnStatement(long where, Expression expr) {
046: super (RETURN, where);
047: this .expr = expr;
048: }
049:
050: /**
051: * Check statement
052: */
053: Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
054: checkLabel(env, ctx);
055: vset = reach(env, vset);
056: if (expr != null) {
057: vset = expr.checkValue(env, ctx, vset, exp);
058: }
059:
060: // Make sure the return isn't inside a static initializer
061: if (ctx.field.isInitializer()) {
062: env.error(where, "return.inside.static.initializer");
063: return DEAD_END;
064: }
065: // Check return type
066: if (ctx.field.getType().getReturnType().isType(TC_VOID)) {
067: if (expr != null) {
068: if (ctx.field.isConstructor()) {
069: env.error(where, "return.with.value.constr",
070: ctx.field);
071: } else {
072: env.error(where, "return.with.value", ctx.field);
073: }
074: expr = null;
075: }
076: } else {
077: if (expr == null) {
078: env.error(where, "return.without.value", ctx.field);
079: } else {
080: expr = convert(env, ctx, ctx.field.getType()
081: .getReturnType(), expr);
082: }
083: }
084: CheckContext mctx = ctx.getReturnContext();
085: if (mctx != null) {
086: mctx.vsBreak = mctx.vsBreak.join(vset);
087: }
088: CheckContext exitctx = ctx.getTryExitContext();
089: if (exitctx != null) {
090: exitctx.vsTryExit = exitctx.vsTryExit.join(vset);
091: }
092: if (expr != null) {
093: // see if we are returning a value out of a try or synchronized
094: // statement. If so, find the outermost one. . . .
095: Node outerFinallyNode = null;
096: for (Context c = ctx; c != null; c = c.prev) {
097: if (c.node == null) {
098: continue;
099: }
100: if (c.node.op == METHOD) {
101: // Don't search outside current method. Fixes 4084230.
102: break;
103: }
104: if (c.node.op == SYNCHRONIZED) {
105: outerFinallyNode = c.node;
106: break;
107: } else if (c.node.op == FINALLY
108: && ((CheckContext) c).vsContinue != null) {
109: outerFinallyNode = c.node;
110: }
111: }
112: if (outerFinallyNode != null) {
113: if (outerFinallyNode.op == FINALLY) {
114: ((FinallyStatement) outerFinallyNode).needReturnSlot = true;
115: } else {
116: ((SynchronizedStatement) outerFinallyNode).needReturnSlot = true;
117: }
118: }
119: }
120: return DEAD_END;
121: }
122:
123: /**
124: * Inline
125: */
126: public Statement inline(Environment env, Context ctx) {
127: if (expr != null) {
128: expr = expr.inlineValue(env, ctx);
129: }
130: return this ;
131: }
132:
133: /**
134: * The cost of inlining this statement
135: */
136: public int costInline(int thresh, Environment env, Context ctx) {
137: return 1 + ((expr != null) ? expr.costInline(thresh, env, ctx)
138: : 0);
139: }
140:
141: /**
142: * Create a copy of the statement for method inlining
143: */
144: public Statement copyInline(Context ctx, boolean valNeeded) {
145: Expression e = (expr != null) ? expr.copyInline(ctx) : null;
146: if ((!valNeeded) && (e != null)) {
147: Statement body[] = { new ExpressionStatement(where, e),
148: new InlineReturnStatement(where, null) };
149: return new CompoundStatement(where, body);
150: }
151: return new InlineReturnStatement(where, e);
152: }
153:
154: /**
155: * Code
156: */
157: public void code(Environment env, Context ctx, Assembler asm) {
158: if (expr == null) {
159: codeFinally(env, ctx, asm, null, null);
160: asm.add(where, opc_return);
161: } else {
162: expr.codeValue(env, ctx, asm);
163: codeFinally(env, ctx, asm, null, expr.type);
164: asm.add(where, opc_ireturn + expr.type.getTypeCodeOffset());
165: }
166: }
167:
168: /**
169: * Print
170: */
171: public void print(PrintStream out, int indent) {
172: super .print(out, indent);
173: out.print("return");
174: if (expr != null) {
175: out.print(" ");
176: expr.print(out);
177: }
178: out.print(";");
179: }
180: }
|