Thu, 05 Jan 2017 18:58:06 +0000
8168774: Polymorhic signature method check crashes javac
Summary: Check for polysig method assumes arity is greater than zero
Reviewed-by: vromero
1 /*
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.code;
28 import java.util.Iterator;
30 import com.sun.tools.javac.tree.JCTree.JCLambda;
31 import com.sun.tools.javac.util.*;
33 /** A type annotation position.
34 *
35 * <p><b>This is NOT part of any supported API.
36 * If you write code that depends on this, you do so at your own risk.
37 * This code and its internal interfaces are subject to change or
38 * deletion without notice.</b>
39 */
40 // Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position
41 public class TypeAnnotationPosition {
43 public enum TypePathEntryKind {
44 ARRAY(0),
45 INNER_TYPE(1),
46 WILDCARD(2),
47 TYPE_ARGUMENT(3);
49 public final int tag;
51 private TypePathEntryKind(int tag) {
52 this.tag = tag;
53 }
54 }
56 public static class TypePathEntry {
57 /** The fixed number of bytes per TypePathEntry. */
58 public static final int bytesPerEntry = 2;
60 public final TypePathEntryKind tag;
61 public final int arg;
63 public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
64 public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
65 public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
67 private TypePathEntry(TypePathEntryKind tag) {
68 Assert.check(tag == TypePathEntryKind.ARRAY ||
69 tag == TypePathEntryKind.INNER_TYPE ||
70 tag == TypePathEntryKind.WILDCARD,
71 "Invalid TypePathEntryKind: " + tag);
72 this.tag = tag;
73 this.arg = 0;
74 }
76 public TypePathEntry(TypePathEntryKind tag, int arg) {
77 Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
78 "Invalid TypePathEntryKind: " + tag);
79 this.tag = tag;
80 this.arg = arg;
81 }
83 public static TypePathEntry fromBinary(int tag, int arg) {
84 Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
85 "Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
86 switch (tag) {
87 case 0:
88 return ARRAY;
89 case 1:
90 return INNER_TYPE;
91 case 2:
92 return WILDCARD;
93 case 3:
94 return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
95 default:
96 Assert.error("Invalid TypePathEntryKind tag: " + tag);
97 return null;
98 }
99 }
101 @Override
102 public String toString() {
103 return tag.toString() +
104 (tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
105 }
107 @Override
108 public boolean equals(Object other) {
109 if (! (other instanceof TypePathEntry)) {
110 return false;
111 }
112 TypePathEntry tpe = (TypePathEntry) other;
113 return this.tag == tpe.tag && this.arg == tpe.arg;
114 }
116 @Override
117 public int hashCode() {
118 return this.tag.hashCode() * 17 + this.arg;
119 }
120 }
122 public TargetType type = TargetType.UNKNOWN;
124 // For generic/array types.
125 public List<TypePathEntry> location = List.nil();
127 // Tree position.
128 public int pos = -1;
130 // For type casts, type tests, new, locals (as start_pc),
131 // and method and constructor reference type arguments.
132 public boolean isValidOffset = false;
133 public int offset = -1;
135 // For locals. arrays same length
136 public int[] lvarOffset = null;
137 public int[] lvarLength = null;
138 public int[] lvarIndex = null;
140 // For type parameter bound
141 public int bound_index = Integer.MIN_VALUE;
143 // For type parameter and method parameter
144 public int parameter_index = Integer.MIN_VALUE;
146 // For class extends, implements, and throws clauses
147 public int type_index = Integer.MIN_VALUE;
149 // For exception parameters, index into exception table.
150 // In com.sun.tools.javac.jvm.Gen.genCatch we first set the type_index
151 // to the catch type index - that value is only temporary.
152 // Then in com.sun.tools.javac.jvm.Code.fillExceptionParameterPositions
153 // we use that value to determine the exception table index.
154 public int exception_index = Integer.MIN_VALUE;
156 // If this type annotation is within a lambda expression,
157 // store a pointer to the lambda expression tree in order
158 // to allow a later translation to the right method.
159 public JCLambda onLambda = null;
161 public TypeAnnotationPosition() {}
163 @Override
164 public String toString() {
165 StringBuilder sb = new StringBuilder();
166 sb.append('[');
167 sb.append(type);
169 switch (type) {
170 // instanceof
171 case INSTANCEOF:
172 // new expression
173 case NEW:
174 // constructor/method reference receiver
175 case CONSTRUCTOR_REFERENCE:
176 case METHOD_REFERENCE:
177 sb.append(", offset = ");
178 sb.append(offset);
179 break;
180 // local variable
181 case LOCAL_VARIABLE:
182 // resource variable
183 case RESOURCE_VARIABLE:
184 if (lvarOffset == null) {
185 sb.append(", lvarOffset is null!");
186 break;
187 }
188 sb.append(", {");
189 for (int i = 0; i < lvarOffset.length; ++i) {
190 if (i != 0) sb.append("; ");
191 sb.append("start_pc = ");
192 sb.append(lvarOffset[i]);
193 sb.append(", length = ");
194 sb.append(lvarLength[i]);
195 sb.append(", index = ");
196 sb.append(lvarIndex[i]);
197 }
198 sb.append("}");
199 break;
200 // method receiver
201 case METHOD_RECEIVER:
202 // Do nothing
203 break;
204 // type parameter
205 case CLASS_TYPE_PARAMETER:
206 case METHOD_TYPE_PARAMETER:
207 sb.append(", param_index = ");
208 sb.append(parameter_index);
209 break;
210 // type parameter bound
211 case CLASS_TYPE_PARAMETER_BOUND:
212 case METHOD_TYPE_PARAMETER_BOUND:
213 sb.append(", param_index = ");
214 sb.append(parameter_index);
215 sb.append(", bound_index = ");
216 sb.append(bound_index);
217 break;
218 // class extends or implements clause
219 case CLASS_EXTENDS:
220 sb.append(", type_index = ");
221 sb.append(type_index);
222 break;
223 // throws
224 case THROWS:
225 sb.append(", type_index = ");
226 sb.append(type_index);
227 break;
228 // exception parameter
229 case EXCEPTION_PARAMETER:
230 sb.append(", exception_index = ");
231 sb.append(exception_index);
232 break;
233 // method parameter
234 case METHOD_FORMAL_PARAMETER:
235 sb.append(", param_index = ");
236 sb.append(parameter_index);
237 break;
238 // type cast
239 case CAST:
240 // method/constructor/reference type argument
241 case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
242 case METHOD_INVOCATION_TYPE_ARGUMENT:
243 case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
244 case METHOD_REFERENCE_TYPE_ARGUMENT:
245 sb.append(", offset = ");
246 sb.append(offset);
247 sb.append(", type_index = ");
248 sb.append(type_index);
249 break;
250 // We don't need to worry about these
251 case METHOD_RETURN:
252 case FIELD:
253 break;
254 case UNKNOWN:
255 sb.append(", position UNKNOWN!");
256 break;
257 default:
258 Assert.error("Unknown target type: " + type);
259 }
261 // Append location data for generics/arrays.
262 if (!location.isEmpty()) {
263 sb.append(", location = (");
264 sb.append(location);
265 sb.append(")");
266 }
268 sb.append(", pos = ");
269 sb.append(pos);
271 if (onLambda != null) {
272 sb.append(", onLambda hash = ");
273 sb.append(onLambda.hashCode());
274 }
276 sb.append(']');
277 return sb.toString();
278 }
280 /**
281 * Indicates whether the target tree of the annotation has been optimized
282 * away from classfile or not.
283 * @return true if the target has not been optimized away
284 */
285 public boolean emitToClassfile() {
286 return !type.isLocal() || isValidOffset;
287 }
290 public boolean matchesPos(int pos) {
291 return this.pos == pos;
292 }
294 public void updatePosOffset(int to) {
295 offset = to;
296 lvarOffset = new int[]{to};
297 isValidOffset = true;
298 }
300 /**
301 * Decode the binary representation for a type path and set
302 * the {@code location} field.
303 *
304 * @param list The bytecode representation of the type path.
305 */
306 public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) {
307 ListBuffer<TypePathEntry> loc = new ListBuffer<>();
308 Iterator<Integer> iter = list.iterator();
309 while (iter.hasNext()) {
310 Integer fst = iter.next();
311 Assert.check(iter.hasNext(), "Could not decode type path: " + list);
312 Integer snd = iter.next();
313 loc = loc.append(TypePathEntry.fromBinary(fst, snd));
314 }
315 return loc.toList();
316 }
318 public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) {
319 ListBuffer<Integer> loc = new ListBuffer<>();
320 for (TypePathEntry tpe : locs) {
321 loc = loc.append(tpe.tag.tag);
322 loc = loc.append(tpe.arg);
323 }
324 return loc.toList();
325 }
326 }