diff options
author | Paul Phillips <paulp@improving.org> | 2011-01-22 19:05:46 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-01-22 19:05:46 +0000 |
commit | 647d23d801a14a2bdd5e740325ef7d099aea15d7 (patch) | |
tree | eda85c1a0c676acbaa2679572bf692eaafa05d1e | |
parent | 2432afcc61db2b08ad66f5335c4c1b18afe9f36d (diff) | |
download | scala-647d23d801a14a2bdd5e740325ef7d099aea15d7.tar.gz scala-647d23d801a14a2bdd5e740325ef7d099aea15d7.tar.bz2 scala-647d23d801a14a2bdd5e740325ef7d099aea15d7.zip |
Merge branch 'invalid-sig' of /scala/trunk
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala | 54 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/SigParser.scala | 15 |
3 files changed, 44 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index df0220ffe3..fd210dd35e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -82,17 +82,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid { */ class BytecodeGenerator extends BytecodeUtil { def debugLevel = settings.debuginfo.indexOfChoice - import scala.tools.reflect.SigParser - def verifySig(sym: Symbol, sig: String) = { - val ok = - if (sym.isMethod) SigParser verifyMethod sig - else if (sym.isTerm) SigParser verifyType sig - else SigParser verifyClass sig - - def label = if (ok) "[ OK ] " else "[BAD!] " - if (settings.verbose.value || !ok) - println(label + sym + " in " + sym.owner.skipPackageObject.fullName + "\n " + sig) - } val MIN_SWITCH_DENSITY = 0.7 val INNER_CLASSES_FLAGS = @@ -523,6 +512,17 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid { nannots } + /** Run the signature parser to catch bogus signatures. + * XXX But we should not be generating bogus signatures! + * The ticket is #4067. + */ + import scala.tools.reflect.SigParser + def isValidSignature(sym: Symbol, sig: String) = ( + if (sym.isMethod) SigParser verifyMethod sig + else if (sym.isTerm) SigParser verifyType sig + else SigParser verifyClass sig + ) + // @M don't generate java generics sigs for (members of) implementation // classes, as they are monomorphic (TODO: ok?) private def noGenericSignature(sym: Symbol) = ( @@ -543,17 +543,29 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid { // println("addGenericSignature sym: " + sym.fullName + " : " + memberTpe + " sym.info: " + sym.info) // println("addGenericSignature: "+ (sym.ownerChain map (x => (x.name, x.isImplClass)))) erasure.javaSig(sym, memberTpe) foreach { sig => - if (settings.Yverifysigs.value) - verifySig(sym, sig) + /** Since we're using a sun internal class for signature validation, + * we have to allow for it not existing or otherwise malfunctioning: + * in which case we treat every signature as valid. Medium term we + * should certainly write independent signature validation. + */ + if (!SigParser.isParserAvailable || isValidSignature(sym, sig)) { + val index = jmember.getConstantPool.addUtf8(sig).toShort + if (opt.verboseDebug) + atPhase(currentRun.erasurePhase) { + println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index) + } + val buf = ByteBuffer.allocate(2) + buf putShort index + addAttribute(jmember, tpnme.SignatureATTR, buf) + } + else { + val msg = "!! Suppressing invalid generic sig for %s in %s: %s".format( + sym, sym.owner.skipPackageObject.fullName, sig + ) - val index = jmember.getConstantPool.addUtf8(sig).toShort - if (opt.verboseDebug) - atPhase(currentRun.erasurePhase) { - println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index) - } - val buf = ByteBuffer.allocate(2) - buf putShort index - addAttribute(jmember, tpnme.SignatureATTR, buf) + if (settings.Yverifysigs.value) Console.println(msg) + else log(msg) + } } } } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 464aedded1..e10abf6a0d 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -108,7 +108,7 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings { val log = PhasesSetting ("-Ylog", "Log operations during") val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.") val Ynogenericsig = BooleanSetting ("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.") - val Yverifysigs = BooleanSetting ("-Yverify-generics", "Validated generated generic signatures.") + val Yverifysigs = BooleanSetting ("-Yverify-generics", "Output a message when an invalid generic signature is suppressed.") val noimports = BooleanSetting ("-Yno-imports", "Compile without any implicit imports.") // Not actually doing anything, so disabled. // val nopredefs = BooleanSetting ("-Yno-predefs", "Compile without any implicit predefined values.") diff --git a/src/compiler/scala/tools/reflect/SigParser.scala b/src/compiler/scala/tools/reflect/SigParser.scala index 7185082175..5d85778570 100644 --- a/src/compiler/scala/tools/reflect/SigParser.scala +++ b/src/compiler/scala/tools/reflect/SigParser.scala @@ -6,29 +6,34 @@ package scala.tools package reflect -import java.lang.reflect.GenericSignatureFormatError +import java.lang.reflect.{ GenericSignatureFormatError, Method } /** The usual reflection song and dance to avoid referencing * any sun.* classes. */ class SigParser { val SunSignatureParser = "sun.reflect.generics.parser.SignatureParser" - lazy val makeMethod = Class.forName(SunSignatureParser) getMethod "make" + private lazy val makeMethod: Method = + try Class.forName(SunSignatureParser) getMethod "make" + catch { case t => null } + def make() = makeMethod.invoke(null).asInstanceOf[SignatureParserInterface] private def wrap(op: => Any) = try { op ; true } catch { case _: GenericSignatureFormatError => false } - def verifyClass(s: String) = wrap(make() parseClassSig s) - def verifyMethod(s: String) = wrap(make() parseMethodSig s) - def verifyType(s: String) = wrap(make() parseTypeSig s) + def isParserAvailable = makeMethod != null + def verifyClass(s: String) = isParserAvailable && wrap(make() parseClassSig s) + def verifyMethod(s: String) = isParserAvailable && wrap(make() parseMethodSig s) + def verifyType(s: String) = isParserAvailable && wrap(make() parseTypeSig s) type ClassSignature <: AnyRef type MethodTypeSignature <: AnyRef type TypeSignature <: AnyRef type SignatureParserInterface = { + def isParserAvailable: Boolean def parseClassSig(s: String): ClassSignature def parseMethodSig(s: String): MethodTypeSignature def parseTypeSig(s: String): TypeSignature |