Tue, 13 Oct 2009 15:26:30 -0700
6891079: Compiler allows invalid binary literals 0b and oBL
Reviewed-by: darcy
1 /*
2 * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.classfile;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.EnumSet;
31 import java.util.List;
32 import java.util.Set;
34 import static com.sun.tools.classfile.ExtendedAnnotation.TargetAttribute.*;
36 /**
37 * See JSR 308 specification, section 4.1
38 *
39 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
40 * you write code that depends on this, you do so at your own risk.
41 * This code and its internal interfaces are subject to change or
42 * deletion without notice.</b>
43 */
44 public class ExtendedAnnotation {
45 ExtendedAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
46 annotation = new Annotation(cr);
47 position = read_position(cr);
48 }
50 public ExtendedAnnotation(ConstantPool constant_pool,
51 Annotation annotation, Position position) {
52 this.annotation = annotation;
53 this.position = position;
54 }
56 public int length() {
57 int n = annotation.length();
58 n += position_length(position);
59 return n;
60 }
62 public final Annotation annotation;
63 public final Position position;
65 private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
66 // Copied from ClassReader
67 int tag = (byte)cr.readUnsignedByte(); // cast to introduce signedness
68 if (!TargetType.isValidTargetTypeValue(tag))
69 throw new Annotation.InvalidAnnotation("invalid type annotation target type value: " + tag);
71 TargetType type = TargetType.fromTargetTypeValue(tag);
73 Position position = new Position();
74 position.type = type;
76 switch (type) {
77 // type case
78 case TYPECAST:
79 case TYPECAST_GENERIC_OR_ARRAY:
80 // object creation
81 case INSTANCEOF:
82 case INSTANCEOF_GENERIC_OR_ARRAY:
83 // new expression
84 case NEW:
85 case NEW_GENERIC_OR_ARRAY:
86 position.offset = cr.readUnsignedShort();
87 break;
88 // local variable
89 case LOCAL_VARIABLE:
90 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
91 int table_length = cr.readUnsignedShort();
92 position.lvarOffset = new int[table_length];
93 position.lvarLength = new int[table_length];
94 position.lvarIndex = new int[table_length];
95 for (int i = 0; i < table_length; ++i) {
96 position.lvarOffset[i] = cr.readUnsignedShort();
97 position.lvarLength[i] = cr.readUnsignedShort();
98 position.lvarIndex[i] = cr.readUnsignedShort();
99 }
100 break;
101 // method receiver
102 case METHOD_RECEIVER:
103 // Do nothing
104 break;
105 // type parameters
106 case CLASS_TYPE_PARAMETER:
107 case METHOD_TYPE_PARAMETER:
108 position.parameter_index = cr.readUnsignedByte();
109 break;
110 // type parameter bounds
111 case CLASS_TYPE_PARAMETER_BOUND:
112 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
113 case METHOD_TYPE_PARAMETER_BOUND:
114 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
115 position.parameter_index = cr.readUnsignedByte();
116 position.bound_index = cr.readUnsignedByte();
117 break;
118 // wildcards
119 case WILDCARD_BOUND:
120 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
121 position.wildcard_position = read_position(cr);
122 break;
123 // Class extends and implements clauses
124 case CLASS_EXTENDS:
125 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
126 position.type_index = cr.readUnsignedByte();
127 break;
128 // throws
129 case THROWS:
130 position.type_index = cr.readUnsignedByte();
131 break;
132 case CLASS_LITERAL:
133 case CLASS_LITERAL_GENERIC_OR_ARRAY:
134 position.offset = cr.readUnsignedShort();
135 break;
136 // method parameter: not specified
137 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
138 position.parameter_index = cr.readUnsignedByte();
139 break;
140 // method type argument: wasn't specified
141 case NEW_TYPE_ARGUMENT:
142 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
143 case METHOD_TYPE_ARGUMENT:
144 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
145 position.offset = cr.readUnsignedShort();
146 position.type_index = cr.readUnsignedByte();
147 break;
148 // We don't need to worry abut these
149 case METHOD_RETURN_GENERIC_OR_ARRAY:
150 case FIELD_GENERIC_OR_ARRAY:
151 break;
152 case UNKNOWN:
153 break;
154 default:
155 throw new AssertionError("Cannot be here");
156 }
158 if (type.hasLocation()) {
159 int len = cr.readUnsignedShort();
160 List<Integer> loc = new ArrayList<Integer>(len);
161 for (int i = 0; i < len; i++)
162 loc.add(cr.readUnsignedByte());
163 position.location = loc;
164 }
165 return position;
166 }
168 private static int position_length(Position pos) {
169 int n = 0;
170 n += 1; // target_type
171 switch (pos.type) {
172 // type case
173 case TYPECAST:
174 case TYPECAST_GENERIC_OR_ARRAY:
175 // object creation
176 case INSTANCEOF:
177 case INSTANCEOF_GENERIC_OR_ARRAY:
178 // new expression
179 case NEW:
180 case NEW_GENERIC_OR_ARRAY:
181 n += 2;
182 break;
183 // local variable
184 case LOCAL_VARIABLE:
185 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
186 n += 2; // table_length;
187 int table_length = pos.lvarOffset.length;
188 n += 2 * table_length; // offset
189 n += 2 * table_length; // length;
190 n += 2 * table_length; // index
191 break;
192 // method receiver
193 case METHOD_RECEIVER:
194 // Do nothing
195 break;
196 // type parameters
197 case CLASS_TYPE_PARAMETER:
198 case METHOD_TYPE_PARAMETER:
199 n += 1; // parameter_index;
200 break;
201 // type parameter bounds
202 case CLASS_TYPE_PARAMETER_BOUND:
203 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
204 case METHOD_TYPE_PARAMETER_BOUND:
205 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
206 n += 1; // parameter_index
207 n += 1; // bound_index
208 break;
209 case WILDCARD_BOUND:
210 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
211 n += position_length(pos.wildcard_position);
212 break;
213 // Class extends and implements clauses
214 case CLASS_EXTENDS:
215 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
216 n += 1; // type_index
217 break;
218 // throws
219 case THROWS:
220 n += 1; // type_index
221 break;
222 case CLASS_LITERAL:
223 case CLASS_LITERAL_GENERIC_OR_ARRAY:
224 n += 1; // offset
225 break;
226 // method parameter: not specified
227 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
228 n += 1; // parameter_index
229 break;
230 // method type argument: wasn't specified
231 case NEW_TYPE_ARGUMENT:
232 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
233 case METHOD_TYPE_ARGUMENT:
234 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
235 n += 2; // offset
236 n += 1; // type index
237 break;
238 // We don't need to worry abut these
239 case METHOD_RETURN_GENERIC_OR_ARRAY:
240 case FIELD_GENERIC_OR_ARRAY:
241 break;
242 case UNKNOWN:
243 break;
244 default:
245 }
247 if (pos.type.hasLocation()) {
248 n += 2; // length
249 n += 1 * pos.location.size(); // actual array size
250 }
252 return n;
253 }
255 // Code duplicated from com.sun.tools.javac.code.TypeAnnotations.Position
256 public static class Position {
258 public TargetType type = TargetType.UNKNOWN;
260 // For generic/array types.
261 public List<Integer> location = new ArrayList<Integer>();
263 // For typecasts, type tests, new (and locals, as start_pc).
264 public int offset = -1;
266 // For locals.
267 public int[] lvarOffset = new int[] { -1 };
268 public int[] lvarLength = new int[] { -1 };
269 public int[] lvarIndex = new int[] { -1 };
271 // For type parameter bound
272 public int bound_index = -1;
274 // For type parameter and method parameter
275 public int parameter_index = -1;
277 // For class extends, implements, and throws classes
278 public int type_index = -2;
280 // For wildcards
281 public Position wildcard_position = null;
283 @Override
284 public String toString() {
285 StringBuilder sb = new StringBuilder();
286 sb.append('[');
287 sb.append(type);
289 switch (type) {
290 // type case
291 case TYPECAST:
292 case TYPECAST_GENERIC_OR_ARRAY:
293 // object creation
294 case INSTANCEOF:
295 case INSTANCEOF_GENERIC_OR_ARRAY:
296 // new expression
297 case NEW:
298 case NEW_GENERIC_OR_ARRAY:
299 case NEW_TYPE_ARGUMENT:
300 case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
301 sb.append(", offset = ");
302 sb.append(offset);
303 break;
304 // local variable
305 case LOCAL_VARIABLE:
306 case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
307 sb.append(", {");
308 for (int i = 0; i < lvarOffset.length; ++i) {
309 if (i != 0) sb.append("; ");
310 sb.append(", start_pc = ");
311 sb.append(lvarOffset[i]);
312 sb.append(", length = ");
313 sb.append(lvarLength[i]);
314 sb.append(", index = ");
315 sb.append(lvarIndex[i]);
316 }
317 sb.append("}");
318 break;
319 // method receiver
320 case METHOD_RECEIVER:
321 // Do nothing
322 break;
323 // type parameters
324 case CLASS_TYPE_PARAMETER:
325 case METHOD_TYPE_PARAMETER:
326 sb.append(", param_index = ");
327 sb.append(parameter_index);
328 break;
329 // type parameters bound
330 case CLASS_TYPE_PARAMETER_BOUND:
331 case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
332 case METHOD_TYPE_PARAMETER_BOUND:
333 case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
334 sb.append(", param_index = ");
335 sb.append(parameter_index);
336 sb.append(", bound_index = ");
337 sb.append(bound_index);
338 break;
339 // wildcard
340 case WILDCARD_BOUND:
341 case WILDCARD_BOUND_GENERIC_OR_ARRAY:
342 sb.append(", wild_card = ");
343 sb.append(wildcard_position);
344 break;
345 // Class extends and implements clauses
346 case CLASS_EXTENDS:
347 case CLASS_EXTENDS_GENERIC_OR_ARRAY:
348 sb.append(", type_index = ");
349 sb.append(type_index);
350 break;
351 // throws
352 case THROWS:
353 sb.append(", type_index = ");
354 sb.append(type_index);
355 break;
356 case CLASS_LITERAL:
357 case CLASS_LITERAL_GENERIC_OR_ARRAY:
358 sb.append(", offset = ");
359 sb.append(offset);
360 break;
361 // method parameter: not specified
362 case METHOD_PARAMETER_GENERIC_OR_ARRAY:
363 sb.append(", param_index = ");
364 sb.append(parameter_index);
365 break;
366 // method type argument: wasn't specified
367 case METHOD_TYPE_ARGUMENT:
368 case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
369 sb.append(", offset = ");
370 sb.append(offset);
371 sb.append(", type_index = ");
372 sb.append(type_index);
373 break;
374 // We don't need to worry abut these
375 case METHOD_RETURN_GENERIC_OR_ARRAY:
376 case FIELD_GENERIC_OR_ARRAY:
377 break;
378 case UNKNOWN:
379 break;
380 default:
381 throw new AssertionError("unknown type: " + type);
382 }
384 // Append location data for generics/arrays.
385 if (type.hasLocation()) {
386 sb.append(", location = (");
387 sb.append(location);
388 sb.append(")");
389 }
391 sb.append(']');
392 return sb.toString();
393 }
394 }
396 // Code duplicated from com.sun.tools.javac.comp.TargetType
397 public enum TargetType {
399 /** For annotations on typecasts. */
400 TYPECAST(0x00),
402 /** For annotations on a type argument or nested array of a typecast. */
403 TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation),
405 /** For annotations on type tests. */
406 INSTANCEOF(0x02),
408 /** For annotations on a type argument or nested array of a type test. */
409 INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation),
411 /** For annotations on object creation expressions. */
412 NEW(0x04),
414 /**
415 * For annotations on a type argument or nested array of an object creation
416 * expression.
417 */
418 NEW_GENERIC_OR_ARRAY(0x05, HasLocation),
421 /** For annotations on the method receiver. */
422 METHOD_RECEIVER(0x06),
424 // invalid location
425 // METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation),
427 /** For annotations on local variables. */
428 LOCAL_VARIABLE(0x08),
430 /** For annotations on a type argument or nested array of a local. */
431 LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation),
433 // already handled by regular annotations
434 // METHOD_RETURN(0x0A),
436 /**
437 * For annotations on a type argument or nested array of a method return
438 * type.
439 */
440 METHOD_RETURN_GENERIC_OR_ARRAY(0x0B, HasLocation),
442 // already handled by regular annotations
443 // METHOD_PARAMETER(0x0C),
445 /** For annotations on a type argument or nested array of a method parameter. */
446 METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation),
448 // already handled by regular annotations
449 // FIELD(0x0E),
451 /** For annotations on a type argument or nested array of a field. */
452 FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation),
454 /** For annotations on a bound of a type parameter of a class. */
455 CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter),
457 /**
458 * For annotations on a type argument or nested array of a bound of a type
459 * parameter of a class.
460 */
461 CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x11, HasBound, HasLocation, HasParameter),
463 /** For annotations on a bound of a type parameter of a method. */
464 METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter),
466 /**
467 * For annotations on a type argument or nested array of a bound of a type
468 * parameter of a method.
469 */
470 METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x13, HasBound, HasLocation, HasParameter),
472 /** For annotations on the type of an "extends" or "implements" clause. */
473 CLASS_EXTENDS(0x14),
475 /** For annotations on the inner type of an "extends" or "implements" clause. */
476 CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation),
478 /** For annotations on a throws clause in a method declaration. */
479 THROWS(0x16),
481 // invalid location
482 // THROWS_GENERIC_OR_ARRAY(0x17, HasLocation),
484 /** For annotations in type arguments of object creation expressions. */
485 NEW_TYPE_ARGUMENT(0x18),
486 NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation),
488 METHOD_TYPE_ARGUMENT(0x1A),
489 METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation),
491 WILDCARD_BOUND(0x1C, HasBound),
492 WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation),
494 CLASS_LITERAL(0x1E),
495 CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation),
497 METHOD_TYPE_PARAMETER(0x20, HasParameter),
499 // invalid location
500 // METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter),
502 CLASS_TYPE_PARAMETER(0x22, HasParameter),
504 // invalid location
505 // CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter),
507 /** For annotations with an unknown target. */
508 UNKNOWN(-1);
510 static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
512 private final int targetTypeValue;
513 private Set<TargetAttribute> flags;
515 TargetType(int targetTypeValue, TargetAttribute... attrs) {
516 if (targetTypeValue < Byte.MIN_VALUE
517 || targetTypeValue > Byte.MAX_VALUE)
518 throw new AssertionError("attribute type value needs to be a byte: " + targetTypeValue);
519 this.targetTypeValue = (byte)targetTypeValue;
520 this.flags = EnumSet.noneOf(TargetAttribute.class);
521 for (TargetAttribute attr : attrs)
522 this.flags.add(attr);
523 }
525 /**
526 * Returns whether or not this TargetType represents an annotation whose
527 * target is an inner type of a generic or array type.
528 *
529 * @return true if this TargetType represents an annotation on an inner
530 * type, false otherwise
531 */
532 public boolean hasLocation() {
533 return flags.contains(HasLocation);
534 }
536 public TargetType getGenericComplement() {
537 if (hasLocation())
538 return this;
539 else
540 return fromTargetTypeValue(targetTypeValue() + 1);
541 }
543 /**
544 * Returns whether or not this TargetType represents an annotation whose
545 * target has a parameter index.
546 *
547 * @return true if this TargetType has a parameter index,
548 * false otherwise
549 */
550 public boolean hasParameter() {
551 return flags.contains(HasParameter);
552 }
554 /**
555 * Returns whether or not this TargetType represents an annotation whose
556 * target is a type parameter bound.
557 *
558 * @return true if this TargetType represents an type parameter bound
559 * annotation, false otherwise
560 */
561 public boolean hasBound() {
562 return flags.contains(HasBound);
563 }
565 public int targetTypeValue() {
566 return this.targetTypeValue;
567 }
569 private static TargetType[] targets = null;
571 private static TargetType[] buildTargets() {
572 TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
573 TargetType[] alltargets = values();
574 for (TargetType target : alltargets)
575 if (target.targetTypeValue >= 0)
576 targets[target.targetTypeValue] = target;
577 for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i)
578 if (targets[i] == null)
579 targets[i] = UNKNOWN;
580 return targets;
581 }
583 public static boolean isValidTargetTypeValue(int tag) {
584 if (targets == null)
585 targets = buildTargets();
587 if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
588 return true;
590 return (tag >= 0 && tag < targets.length);
591 }
593 public static TargetType fromTargetTypeValue(int tag) {
594 if (targets == null)
595 targets = buildTargets();
597 if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
598 return UNKNOWN;
600 if (tag < 0 || tag >= targets.length)
601 throw new IllegalArgumentException("Unknown TargetType: " + tag);
602 return targets[tag];
603 }
604 }
606 static enum TargetAttribute {
607 HasLocation, HasParameter, HasBound;
608 }
609 }