summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-06-19 12:58:38 -0700
committerGrzegorz Kossakowski <grzegorz.kossakowski@gmail.com>2013-06-19 12:58:38 -0700
commitf467940e5980621f8c288f8d47656061b1a0f15d (patch)
tree0c7475ae78a68d57b417cc2e7a7ec67808719d0f
parent16ea58b34b37947f40b3d9f90356a64099b250a7 (diff)
parentb49b6cf7f0f42d74da854d96eeb0f863357c04cd (diff)
downloadscala-f467940e5980621f8c288f8d47656061b1a0f15d.tar.gz
scala-f467940e5980621f8c288f8d47656061b1a0f15d.tar.bz2
scala-f467940e5980621f8c288f8d47656061b1a0f15d.zip
Merge pull request #2635 from retronym/ticket/7151
SI-7151 Emit final in bytecode for final inner classes.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala5
-rw-r--r--test/files/run/t7151.check6
-rw-r--r--test/files/run/t7151.scala24
3 files changed, 33 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 19a6e11986..ea2cbbe3d3 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -415,7 +415,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
val INNER_CLASSES_FLAGS =
(asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED |
- asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT)
+ asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_FINAL)
// -----------------------------------------------------------------------------------------
// factory methods
@@ -648,11 +648,12 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// sort them so inner classes succeed their enclosing class to satisfy the Eclipse Java compiler
for (innerSym <- allInners sortBy (_.name.length)) { // TODO why not sortBy (_.name.toString()) ??
- val flags = mkFlags(
+ val flagsWithFinal: Int = mkFlags(
if (innerSym.rawowner.hasModuleFlag) asm.Opcodes.ACC_STATIC else 0,
javaFlags(innerSym),
if(isDeprecated(innerSym)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo-access flag
) & (INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED)
+ val flags = if (innerSym.isModuleClass) flagsWithFinal & ~asm.Opcodes.ACC_FINAL else flagsWithFinal // For SI-5676, object overriding.
val jname = javaName(innerSym) // never null
val oname = outerName(innerSym) // null when method-enclosed
val iname = innerName(innerSym) // null for anonymous inner class
diff --git a/test/files/run/t7151.check b/test/files/run/t7151.check
new file mode 100644
index 0000000000..d532d9589f
--- /dev/null
+++ b/test/files/run/t7151.check
@@ -0,0 +1,6 @@
+class Test$InnerObject$ isFinal = false
+class Test$InnerCase isFinal = true
+class Test$InnerNonCase isFinal = true
+class TopLevelObject$ isFinal = true
+class TopLevelCase isFinal = true
+class TopLevelNonCase isFinal = true
diff --git a/test/files/run/t7151.scala b/test/files/run/t7151.scala
new file mode 100644
index 0000000000..f6492ba43c
--- /dev/null
+++ b/test/files/run/t7151.scala
@@ -0,0 +1,24 @@
+import java.lang.reflect.Modifier.isFinal
+
+object Test {
+ object InnerObject
+ final case class InnerCase()
+ final class InnerNonCase()
+
+ def main(args: Array[String]) {
+ def checkFinal(clazz: Class[_]) =
+ println(s"${clazz} isFinal = ${isFinal(clazz.getModifiers())}")
+
+ checkFinal(InnerObject.getClass)
+ checkFinal(classOf[InnerCase])
+ checkFinal(classOf[InnerNonCase])
+
+ checkFinal(TopLevelObject.getClass)
+ checkFinal(classOf[TopLevelCase])
+ checkFinal(classOf[TopLevelNonCase])
+ }
+}
+
+object TopLevelObject
+final case class TopLevelCase()
+final case class TopLevelNonCase()