xref: /aosp_15_r20/external/javassist/src/main/javassist/expr/Cast.java (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
1*f1fbf3c2SXin Li /*
2*f1fbf3c2SXin Li  * Javassist, a Java-bytecode translator toolkit.
3*f1fbf3c2SXin Li  * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4*f1fbf3c2SXin Li  *
5*f1fbf3c2SXin Li  * The contents of this file are subject to the Mozilla Public License Version
6*f1fbf3c2SXin Li  * 1.1 (the "License"); you may not use this file except in compliance with
7*f1fbf3c2SXin Li  * the License.  Alternatively, the contents of this file may be used under
8*f1fbf3c2SXin Li  * the terms of the GNU Lesser General Public License Version 2.1 or later,
9*f1fbf3c2SXin Li  * or the Apache License Version 2.0.
10*f1fbf3c2SXin Li  *
11*f1fbf3c2SXin Li  * Software distributed under the License is distributed on an "AS IS" basis,
12*f1fbf3c2SXin Li  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13*f1fbf3c2SXin Li  * for the specific language governing rights and limitations under the
14*f1fbf3c2SXin Li  * License.
15*f1fbf3c2SXin Li  */
16*f1fbf3c2SXin Li 
17*f1fbf3c2SXin Li package javassist.expr;
18*f1fbf3c2SXin Li 
19*f1fbf3c2SXin Li import javassist.CannotCompileException;
20*f1fbf3c2SXin Li import javassist.ClassPool;
21*f1fbf3c2SXin Li import javassist.CtBehavior;
22*f1fbf3c2SXin Li import javassist.CtClass;
23*f1fbf3c2SXin Li import javassist.NotFoundException;
24*f1fbf3c2SXin Li import javassist.bytecode.BadBytecode;
25*f1fbf3c2SXin Li import javassist.bytecode.Bytecode;
26*f1fbf3c2SXin Li import javassist.bytecode.CodeAttribute;
27*f1fbf3c2SXin Li import javassist.bytecode.CodeIterator;
28*f1fbf3c2SXin Li import javassist.bytecode.ConstPool;
29*f1fbf3c2SXin Li import javassist.bytecode.MethodInfo;
30*f1fbf3c2SXin Li import javassist.bytecode.Opcode;
31*f1fbf3c2SXin Li import javassist.compiler.CompileError;
32*f1fbf3c2SXin Li import javassist.compiler.Javac;
33*f1fbf3c2SXin Li import javassist.compiler.JvstCodeGen;
34*f1fbf3c2SXin Li import javassist.compiler.JvstTypeChecker;
35*f1fbf3c2SXin Li import javassist.compiler.ProceedHandler;
36*f1fbf3c2SXin Li import javassist.compiler.ast.ASTList;
37*f1fbf3c2SXin Li 
38*f1fbf3c2SXin Li /**
39*f1fbf3c2SXin Li  * Explicit type cast.
40*f1fbf3c2SXin Li  */
41*f1fbf3c2SXin Li public class Cast extends Expr {
42*f1fbf3c2SXin Li     /**
43*f1fbf3c2SXin Li      * Undocumented constructor.  Do not use; internal-use only.
44*f1fbf3c2SXin Li      */
Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m)45*f1fbf3c2SXin Li     protected Cast(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
46*f1fbf3c2SXin Li         super(pos, i, declaring, m);
47*f1fbf3c2SXin Li     }
48*f1fbf3c2SXin Li 
49*f1fbf3c2SXin Li     /**
50*f1fbf3c2SXin Li      * Returns the method or constructor containing the type cast
51*f1fbf3c2SXin Li      * expression represented by this object.
52*f1fbf3c2SXin Li      */
53*f1fbf3c2SXin Li     @Override
where()54*f1fbf3c2SXin Li     public CtBehavior where() { return super.where(); }
55*f1fbf3c2SXin Li 
56*f1fbf3c2SXin Li     /**
57*f1fbf3c2SXin Li      * Returns the line number of the source line containing the
58*f1fbf3c2SXin Li      * type-cast expression.
59*f1fbf3c2SXin Li      *
60*f1fbf3c2SXin Li      * @return -1       if this information is not available.
61*f1fbf3c2SXin Li      */
62*f1fbf3c2SXin Li     @Override
getLineNumber()63*f1fbf3c2SXin Li     public int getLineNumber() {
64*f1fbf3c2SXin Li         return super.getLineNumber();
65*f1fbf3c2SXin Li     }
66*f1fbf3c2SXin Li 
67*f1fbf3c2SXin Li     /**
68*f1fbf3c2SXin Li      * Returns the source file containing the type-cast expression.
69*f1fbf3c2SXin Li      *
70*f1fbf3c2SXin Li      * @return null     if this information is not available.
71*f1fbf3c2SXin Li      */
72*f1fbf3c2SXin Li     @Override
getFileName()73*f1fbf3c2SXin Li     public String getFileName() {
74*f1fbf3c2SXin Li         return super.getFileName();
75*f1fbf3c2SXin Li     }
76*f1fbf3c2SXin Li 
77*f1fbf3c2SXin Li     /**
78*f1fbf3c2SXin Li      * Returns the <code>CtClass</code> object representing
79*f1fbf3c2SXin Li      * the type specified by the cast.
80*f1fbf3c2SXin Li      */
getType()81*f1fbf3c2SXin Li     public CtClass getType() throws NotFoundException {
82*f1fbf3c2SXin Li         ConstPool cp = getConstPool();
83*f1fbf3c2SXin Li         int pos = currentPos;
84*f1fbf3c2SXin Li         int index = iterator.u16bitAt(pos + 1);
85*f1fbf3c2SXin Li         String name = cp.getClassInfo(index);
86*f1fbf3c2SXin Li         return thisClass.getClassPool().getCtClass(name);
87*f1fbf3c2SXin Li     }
88*f1fbf3c2SXin Li 
89*f1fbf3c2SXin Li     /**
90*f1fbf3c2SXin Li      * Returns the list of exceptions that the expression may throw.
91*f1fbf3c2SXin Li      * This list includes both the exceptions that the try-catch statements
92*f1fbf3c2SXin Li      * including the expression can catch and the exceptions that
93*f1fbf3c2SXin Li      * the throws declaration allows the method to throw.
94*f1fbf3c2SXin Li      */
95*f1fbf3c2SXin Li     @Override
mayThrow()96*f1fbf3c2SXin Li     public CtClass[] mayThrow() {
97*f1fbf3c2SXin Li         return super.mayThrow();
98*f1fbf3c2SXin Li     }
99*f1fbf3c2SXin Li 
100*f1fbf3c2SXin Li     /**
101*f1fbf3c2SXin Li      * Replaces the explicit cast operator with the bytecode derived from
102*f1fbf3c2SXin Li      * the given source text.
103*f1fbf3c2SXin Li      *
104*f1fbf3c2SXin Li      * <p>$0 is available but the value is <code>null</code>.
105*f1fbf3c2SXin Li      *
106*f1fbf3c2SXin Li      * @param statement         a Java statement except try-catch.
107*f1fbf3c2SXin Li      */
108*f1fbf3c2SXin Li     @Override
replace(String statement)109*f1fbf3c2SXin Li     public void replace(String statement) throws CannotCompileException {
110*f1fbf3c2SXin Li         thisClass.getClassFile();   // to call checkModify().
111*f1fbf3c2SXin Li         @SuppressWarnings("unused")
112*f1fbf3c2SXin Li         ConstPool constPool = getConstPool();
113*f1fbf3c2SXin Li         int pos = currentPos;
114*f1fbf3c2SXin Li         int index = iterator.u16bitAt(pos + 1);
115*f1fbf3c2SXin Li 
116*f1fbf3c2SXin Li         Javac jc = new Javac(thisClass);
117*f1fbf3c2SXin Li         ClassPool cp = thisClass.getClassPool();
118*f1fbf3c2SXin Li         CodeAttribute ca = iterator.get();
119*f1fbf3c2SXin Li 
120*f1fbf3c2SXin Li         try {
121*f1fbf3c2SXin Li             CtClass[] params
122*f1fbf3c2SXin Li                 = new CtClass[] { cp.get(javaLangObject) };
123*f1fbf3c2SXin Li             CtClass retType = getType();
124*f1fbf3c2SXin Li 
125*f1fbf3c2SXin Li             int paramVar = ca.getMaxLocals();
126*f1fbf3c2SXin Li             jc.recordParams(javaLangObject, params, true, paramVar,
127*f1fbf3c2SXin Li                             withinStatic());
128*f1fbf3c2SXin Li             int retVar = jc.recordReturnType(retType, true);
129*f1fbf3c2SXin Li             jc.recordProceed(new ProceedForCast(index, retType));
130*f1fbf3c2SXin Li 
131*f1fbf3c2SXin Li             /* Is $_ included in the source code?
132*f1fbf3c2SXin Li              */
133*f1fbf3c2SXin Li             checkResultValue(retType, statement);
134*f1fbf3c2SXin Li 
135*f1fbf3c2SXin Li             Bytecode bytecode = jc.getBytecode();
136*f1fbf3c2SXin Li             storeStack(params, true, paramVar, bytecode);
137*f1fbf3c2SXin Li             jc.recordLocalVariables(ca, pos);
138*f1fbf3c2SXin Li 
139*f1fbf3c2SXin Li             bytecode.addConstZero(retType);
140*f1fbf3c2SXin Li             bytecode.addStore(retVar, retType);     // initialize $_
141*f1fbf3c2SXin Li 
142*f1fbf3c2SXin Li             jc.compileStmnt(statement);
143*f1fbf3c2SXin Li             bytecode.addLoad(retVar, retType);
144*f1fbf3c2SXin Li 
145*f1fbf3c2SXin Li             replace0(pos, bytecode, 3);
146*f1fbf3c2SXin Li         }
147*f1fbf3c2SXin Li         catch (CompileError e) { throw new CannotCompileException(e); }
148*f1fbf3c2SXin Li         catch (NotFoundException e) { throw new CannotCompileException(e); }
149*f1fbf3c2SXin Li         catch (BadBytecode e) {
150*f1fbf3c2SXin Li             throw new CannotCompileException("broken method");
151*f1fbf3c2SXin Li         }
152*f1fbf3c2SXin Li     }
153*f1fbf3c2SXin Li 
154*f1fbf3c2SXin Li     /* <type> $proceed(Object obj)
155*f1fbf3c2SXin Li      */
156*f1fbf3c2SXin Li     static class ProceedForCast implements ProceedHandler {
157*f1fbf3c2SXin Li         int index;
158*f1fbf3c2SXin Li         CtClass retType;
159*f1fbf3c2SXin Li 
ProceedForCast(int i, CtClass t)160*f1fbf3c2SXin Li         ProceedForCast(int i, CtClass t) {
161*f1fbf3c2SXin Li             index = i;
162*f1fbf3c2SXin Li             retType = t;
163*f1fbf3c2SXin Li         }
164*f1fbf3c2SXin Li 
165*f1fbf3c2SXin Li         @Override
doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)166*f1fbf3c2SXin Li         public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
167*f1fbf3c2SXin Li             throws CompileError
168*f1fbf3c2SXin Li         {
169*f1fbf3c2SXin Li             if (gen.getMethodArgsLength(args) != 1)
170*f1fbf3c2SXin Li                 throw new CompileError(Javac.proceedName
171*f1fbf3c2SXin Li                         + "() cannot take more than one parameter "
172*f1fbf3c2SXin Li                         + "for cast");
173*f1fbf3c2SXin Li 
174*f1fbf3c2SXin Li             gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
175*f1fbf3c2SXin Li             bytecode.addOpcode(Opcode.CHECKCAST);
176*f1fbf3c2SXin Li             bytecode.addIndex(index);
177*f1fbf3c2SXin Li             gen.setType(retType);
178*f1fbf3c2SXin Li         }
179*f1fbf3c2SXin Li 
180*f1fbf3c2SXin Li         @Override
setReturnType(JvstTypeChecker c, ASTList args)181*f1fbf3c2SXin Li         public void setReturnType(JvstTypeChecker c, ASTList args)
182*f1fbf3c2SXin Li             throws CompileError
183*f1fbf3c2SXin Li         {
184*f1fbf3c2SXin Li             c.atMethodArgs(args, new int[1], new int[1], new String[1]);
185*f1fbf3c2SXin Li             c.setType(retType);
186*f1fbf3c2SXin Li         }
187*f1fbf3c2SXin Li     }
188*f1fbf3c2SXin Li }
189