@@ -314,6 +314,19 @@ class ClassfileParser(
314314 final def objToAny (tp : Type )(implicit ctx : Context ): Type =
315315 if (tp.isDirectRef(defn.ObjectClass ) && ! ctx.phase.erasedTypes) defn.AnyType else tp
316316
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+
317330 private def sigToType (sig : SimpleName , owner : Symbol = null )(implicit ctx : Context ): Type = {
318331 var index = 0
319332 val end = sig.length
@@ -331,15 +344,6 @@ class ClassfileParser(
331344 def sig2type (tparams : immutable.Map [Name , Symbol ], skiptvs : Boolean )(implicit ctx : Context ): Type = {
332345 val tag = sig(index); index += 1
333346 (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
343347 case 'L' =>
344348 def processInner (tp : Type ): Type = tp match {
345349 case tp : TypeRef if ! tp.symbol.owner.is(Flags .ModuleClass ) =>
@@ -417,6 +421,8 @@ class ClassfileParser(
417421 index += 1
418422 // assert(tparams contains n, s"classTparams = $classTParams, tparams = $tparams, key = $n")
419423 if (skiptvs) defn.AnyType else tparams(n).typeRef
424+ case tag =>
425+ constantTagToType(tag)
420426 }
421427 }
422428 // sig2type(tparams, skiptvs)
@@ -495,12 +501,11 @@ class ClassfileParser(
495501 val tag = in.nextByte.toChar
496502 val index = in.nextChar
497503
498-
499504 tag match {
500505 case STRING_TAG =>
501506 if (skip) None else Some (lit(Constant (pool.getName(index).toString)))
502507 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) )))
504509 case INT_TAG | LONG_TAG | FLOAT_TAG | DOUBLE_TAG =>
505510 if (skip) None else Some (lit(pool.getConstant(index)))
506511 case CLASS_TAG =>
@@ -571,11 +576,6 @@ class ClassfileParser(
571576 }
572577
573578 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
579579 var newType = symtype
580580
581581 def parseAttribute (): Unit = {
@@ -597,10 +597,9 @@ class ClassfileParser(
597597 val since = Literal (Constant (" " ))
598598 sym.addAnnotation(Annotation (defn.DeprecatedAnnot , msg, since))
599599 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}" )
604603 case tpnme.AnnotationDefaultATTR =>
605604 sym.addAnnotation(Annotation (defn.AnnotationDefaultAnnot , Nil ))
606605 // Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME
@@ -1113,28 +1112,14 @@ class ClassfileParser(
11131112 getClassSymbol(index)
11141113 }
11151114
1116- def getConstant (index : Int , tag : Int = - 1 )(implicit ctx : Context ): Constant = {
1115+ def getConstant (index : Int , pt : Type = WildcardType )(implicit ctx : Context ): Constant = {
11171116 if (index <= 0 || len <= index) errorBadIndex(index)
11181117 var value = values(index)
11191118 if (value eq null ) {
11201119 val start = starts(index)
11211120 value = (in.buf(start).toInt: @ switch) match {
11221121 case CONSTANT_STRING =>
11231122 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- }
11381123 case CONSTANT_INTEGER =>
11391124 Constant (in.getInt(start + 1 ))
11401125 case CONSTANT_FLOAT =>
@@ -1151,7 +1136,21 @@ class ClassfileParser(
11511136 values(index) = value
11521137 }
11531138 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
11551154 case cls : Symbol => Constant (cls.typeRef)
11561155 case arr : Type => Constant (arr)
11571156 }
0 commit comments