@@ -314,6 +314,19 @@ class ClassfileParser(
314
314
final def objToAny (tp : Type )(implicit ctx : Context ): Type =
315
315
if (tp.isDirectRef(defn.ObjectClass ) && ! ctx.phase.erasedTypes) defn.AnyType else tp
316
316
317
+ def constantTagToType (tag : Int )(using Context ): Type =
318
+ (tag : @ switch) match {
319
+ case BYTE_TAG => defn.ByteType
320
+ case CHAR_TAG => defn.CharType
321
+ case DOUBLE_TAG => defn.DoubleType
322
+ case FLOAT_TAG => defn.FloatType
323
+ case INT_TAG => defn.IntType
324
+ case LONG_TAG => defn.LongType
325
+ case SHORT_TAG => defn.ShortType
326
+ case VOID_TAG => defn.UnitType
327
+ case BOOL_TAG => defn.BooleanType
328
+ }
329
+
317
330
private def sigToType (sig : SimpleName , owner : Symbol = null )(implicit ctx : Context ): Type = {
318
331
var index = 0
319
332
val end = sig.length
@@ -331,15 +344,6 @@ class ClassfileParser(
331
344
def sig2type (tparams : immutable.Map [Name , Symbol ], skiptvs : Boolean )(implicit ctx : Context ): Type = {
332
345
val tag = sig(index); index += 1
333
346
(tag : @ switch) match {
334
- case BYTE_TAG => defn.ByteType
335
- case CHAR_TAG => defn.CharType
336
- case DOUBLE_TAG => defn.DoubleType
337
- case FLOAT_TAG => defn.FloatType
338
- case INT_TAG => defn.IntType
339
- case LONG_TAG => defn.LongType
340
- case SHORT_TAG => defn.ShortType
341
- case VOID_TAG => defn.UnitType
342
- case BOOL_TAG => defn.BooleanType
343
347
case 'L' =>
344
348
def processInner (tp : Type ): Type = tp match {
345
349
case tp : TypeRef if ! tp.symbol.owner.is(Flags .ModuleClass ) =>
@@ -417,6 +421,8 @@ class ClassfileParser(
417
421
index += 1
418
422
// assert(tparams contains n, s"classTparams = $classTParams, tparams = $tparams, key = $n")
419
423
if (skiptvs) defn.AnyType else tparams(n).typeRef
424
+ case tag =>
425
+ constantTagToType(tag)
420
426
}
421
427
}
422
428
// sig2type(tparams, skiptvs)
@@ -495,12 +501,11 @@ class ClassfileParser(
495
501
val tag = in.nextByte.toChar
496
502
val index = in.nextChar
497
503
498
-
499
504
tag match {
500
505
case STRING_TAG =>
501
506
if (skip) None else Some (lit(Constant (pool.getName(index).toString)))
502
507
case BOOL_TAG | BYTE_TAG | CHAR_TAG | SHORT_TAG =>
503
- if (skip) None else Some (lit(pool.getConstant(index, tag)))
508
+ if (skip) None else Some (lit(pool.getConstant(index, constantTagToType( tag) )))
504
509
case INT_TAG | LONG_TAG | FLOAT_TAG | DOUBLE_TAG =>
505
510
if (skip) None else Some (lit(pool.getConstant(index)))
506
511
case CLASS_TAG =>
@@ -571,11 +576,6 @@ class ClassfileParser(
571
576
}
572
577
573
578
def parseAttributes (sym : Symbol , symtype : Type )(implicit ctx : Context ): Type = {
574
- def convertTo (c : Constant , pt : Type ): Constant =
575
- if (pt == defn.BooleanType && c.tag == IntTag )
576
- Constant (c.value != 0 )
577
- else
578
- c convertTo pt
579
579
var newType = symtype
580
580
581
581
def parseAttribute (): Unit = {
@@ -597,10 +597,9 @@ class ClassfileParser(
597
597
val since = Literal (Constant (" " ))
598
598
sym.addAnnotation(Annotation (defn.DeprecatedAnnot , msg, since))
599
599
case tpnme.ConstantValueATTR =>
600
- val c = pool.getConstant(in.nextChar)
601
- val c1 = convertTo(c, symtype)
602
- if (c1 ne null ) newType = ConstantType (c1)
603
- else println(" failure to convert " + c + " to " + symtype); // debug
600
+ val c = pool.getConstant(in.nextChar, symtype)
601
+ if (c ne null ) newType = ConstantType (c)
602
+ else ctx.warning(s " Invalid constant in attribute of ${sym.showLocated} while parsing ${classfile}" )
604
603
case tpnme.AnnotationDefaultATTR =>
605
604
sym.addAnnotation(Annotation (defn.AnnotationDefaultAnnot , Nil ))
606
605
// Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME
@@ -1113,28 +1112,14 @@ class ClassfileParser(
1113
1112
getClassSymbol(index)
1114
1113
}
1115
1114
1116
- def getConstant (index : Int , tag : Int = - 1 )(implicit ctx : Context ): Constant = {
1115
+ def getConstant (index : Int , pt : Type = WildcardType )(implicit ctx : Context ): Constant = {
1117
1116
if (index <= 0 || len <= index) errorBadIndex(index)
1118
1117
var value = values(index)
1119
1118
if (value eq null ) {
1120
1119
val start = starts(index)
1121
1120
value = (in.buf(start).toInt: @ switch) match {
1122
1121
case CONSTANT_STRING =>
1123
1122
Constant (getName(in.getChar(start + 1 ).toInt).toString)
1124
- case CONSTANT_INTEGER if tag != - 1 =>
1125
- val value = in.getInt(start + 1 )
1126
- (tag : @ switch) match {
1127
- case BOOL_TAG =>
1128
- Constant (value != 0 )
1129
- case BYTE_TAG =>
1130
- Constant (value.toByte)
1131
- case CHAR_TAG =>
1132
- Constant (value.toChar)
1133
- case SHORT_TAG =>
1134
- Constant (value.toShort)
1135
- case _ =>
1136
- errorBadTag(tag)
1137
- }
1138
1123
case CONSTANT_INTEGER =>
1139
1124
Constant (in.getInt(start + 1 ))
1140
1125
case CONSTANT_FLOAT =>
@@ -1151,7 +1136,21 @@ class ClassfileParser(
1151
1136
values(index) = value
1152
1137
}
1153
1138
value match {
1154
- case ct : Constant => ct
1139
+ case ct : Constant =>
1140
+ if pt ne WildcardType then
1141
+ // As specified in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1,
1142
+ // an annotation argument of type boolean, byte, char or short will
1143
+ // be represented as a CONSTANT_INTEGER, so we need to convert it to
1144
+ // produce a correctly-typed tree. We need to do this each time the
1145
+ // constant is accessed instead of storing the result of the
1146
+ // conversion in the `values` cache, because the same constant might
1147
+ // be used for annotation arguments of different type.
1148
+ if (pt eq defn.BooleanType ) && ct.tag == IntTag then
1149
+ Constant (ct.value != 0 )
1150
+ else
1151
+ ct.convertTo(pt)
1152
+ else
1153
+ ct
1155
1154
case cls : Symbol => Constant (cls.typeRef)
1156
1155
case arr : Type => Constant (arr)
1157
1156
}
0 commit comments