summaryrefslogtreecommitdiff
path: root/test/junit
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-06-06 11:51:56 -0700
committerAdriaan Moors <adriaan@lightbend.com>2016-06-06 11:51:56 -0700
commit79e7334f93da4717ee846f74e48ab53533e6756d (patch)
tree384f2680be482981370c64c7112aaed14b92cc0f /test/junit
parent28e0e18106a93fd8fd9a086c29836631c754ba35 (diff)
parenta1ea0aa0a6136c13baa41268d7dbd4197924d3c9 (diff)
downloadscala-79e7334f93da4717ee846f74e48ab53533e6756d.tar.gz
scala-79e7334f93da4717ee846f74e48ab53533e6756d.tar.bz2
scala-79e7334f93da4717ee846f74e48ab53533e6756d.zip
Merge pull request #5202 from lrytz/lineNumbers
Keep line numbers when inlining from the same compilation unit
Diffstat (limited to 'test/junit')
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala23
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala24
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala2
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala60
-rw-r--r--test/junit/scala/tools/testing/BytecodeTesting.scala2
5 files changed, 91 insertions, 20 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
index f835e9b140..a28599cd92 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
@@ -88,4 +88,27 @@ class DirectCompileTest extends BytecodeTesting {
def compileErroneous(): Unit = {
compileToBytes("class C { def f: String = 1 }", allowMessage = _.msg contains "type mismatch")
}
+
+ @Test
+ def residentRedefineFinalFlag(): Unit = {
+ val compiler = newCompiler()
+ val a = "final class C { def c1 = 0 }"
+ // for re-defined class symbols (C), the compiler did not clear the `final` flag.
+ // so compiling `D` would give an error `illegal inheritance from final class C`.
+ val b = "class C; class D extends C"
+ compiler.compileToBytes(a)
+ compiler.compileToBytes(b)
+ }
+
+ @Test
+ def residentMultipleRunsNotCompanions(): Unit = {
+ val compiler = newCompiler()
+ val a = List(("public class A { }", "A.java"))
+ // when checking that a class and its companion are defined in the same compilation unit, the
+ // compiler would also emit a warning if the two symbols are defined in separate runs. this
+ // would lead to an error message when compiling the scala class A.
+ val b = "class A"
+ compiler.compileToBytes("", a)
+ compiler.compileToBytes(b)
+ }
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
index 024cf0c416..5254d7e1f2 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlineWarningTest.scala
@@ -97,7 +97,7 @@ class InlineWarningTest extends BytecodeTesting {
@Test
def cannotInlinePrivateCallIntoDifferentClass(): Unit = {
val code =
- """class M {
+ """class A {
| @inline final def f = {
| @noinline def nested = 0
| nested
@@ -106,15 +106,15 @@ class InlineWarningTest extends BytecodeTesting {
| def t = f // ok
|}
|
- |class N {
- | def t(a: M) = a.f // not possible
+ |class B {
+ | def t(a: A) = a.f // not possible
|}
""".stripMargin
val warn =
- """M::f()I is annotated @inline but could not be inlined:
- |The callee M::f()I contains the instruction INVOKESTATIC M.nested$1 ()I
- |that would cause an IllegalAccessError when inlined into class N""".stripMargin
+ """A::f()I is annotated @inline but could not be inlined:
+ |The callee A::f()I contains the instruction INVOKESTATIC A.nested$1 ()I
+ |that would cause an IllegalAccessError when inlined into class B""".stripMargin
var c = 0
compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn })
@@ -124,7 +124,7 @@ class InlineWarningTest extends BytecodeTesting {
@Test
def dontWarnWhenNotIlnineAnnotated(): Unit = {
val code =
- """class M {
+ """class A {
| final def f(t: Int => Int) = {
| @noinline def nested = 0
| nested + t(1)
@@ -132,16 +132,16 @@ class InlineWarningTest extends BytecodeTesting {
| def t = f(x => x + 1)
|}
|
- |class N {
- | def t(a: M) = a.f(x => x + 1)
+ |class B {
+ | def t(a: A) = a.f(x => x + 1)
|}
""".stripMargin
compileToBytes(code, allowMessage = _ => false) // no warnings allowed
val warn =
- """M::f(Lscala/Function1;)I could not be inlined:
- |The callee M::f(Lscala/Function1;)I contains the instruction INVOKESTATIC M.nested$1 ()I
- |that would cause an IllegalAccessError when inlined into class N""".stripMargin
+ """A::f(Lscala/Function1;)I could not be inlined:
+ |The callee A::f(Lscala/Function1;)I contains the instruction INVOKESTATIC A.nested$1 ()I
+ |that would cause an IllegalAccessError when inlined into class B""".stripMargin
var c = 0
compilerWarnAll.compileToBytes(code, allowMessage = i => { c += 1; i.msg contains warn })
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala
index 3cb1fbdae6..3e0b889e9c 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerIllegalAccessTest.scala
@@ -19,7 +19,7 @@ class InlinerIllegalAccessTest extends BytecodeTesting {
import compiler._
import global.genBCode.bTypes._
- def addToRepo(cls: List[ClassNode]): Unit = for (c <- cls) byteCodeRepository.add(c, ByteCodeRepository.Classfile)
+ def addToRepo(cls: List[ClassNode]): Unit = for (c <- cls) byteCodeRepository.add(c, None)
def assertEmpty(ins: Option[AbstractInsnNode]) = for (i <- ins)
throw new AssertionError(textify(i))
diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
index 02cd632af1..9173a1d189 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala
@@ -43,7 +43,7 @@ class InlinerTest extends BytecodeTesting {
// Use the class nodes stored in the byteCodeRepository. The ones returned by compileClasses are not the same,
// these are created new from the classfile byte array. They are completely separate instances which cannot
// be used to look up methods / callsites in the callGraph hash maps for example.
- byteCodeRepository.compilingClasses.valuesIterator.toList.sortBy(_.name)
+ byteCodeRepository.compilingClasses.valuesIterator.map(_._1).toList.sortBy(_.name)
}
def checkCallsite(callsite: callGraph.Callsite, callee: MethodNode) = {
@@ -835,11 +835,11 @@ class InlinerTest extends BytecodeTesting {
@Test
def inlineInvokeSpecial(): Unit = {
val code =
- """class Aa {
+ """class A {
| def f1 = 0
|}
- |class B extends Aa {
- | @inline final override def f1 = 1 + super.f1 // invokespecial Aa.f1
+ |class B extends A {
+ | @inline final override def f1 = 1 + super.f1 // invokespecial A.f1
|
| private def f2m = 0 // public B$$f2m in bytecode
| @inline final def f2 = f2m // invokevirtual B.B$$f2m
@@ -863,13 +863,13 @@ class InlinerTest extends BytecodeTesting {
val warn =
"""B::f1()I is annotated @inline but could not be inlined:
- |The callee B::f1()I contains the instruction INVOKESPECIAL Aa.f1 ()I
+ |The callee B::f1()I contains the instruction INVOKESPECIAL A.f1 ()I
|that would cause an IllegalAccessError when inlined into class T.""".stripMargin
var c = 0
val List(a, b, t) = compile(code, allowMessage = i => {c += 1; i.msg contains warn})
assert(c == 1, c)
- assertInvoke(getMethod(b, "t1"), "Aa", "f1")
+ assertInvoke(getMethod(b, "t1"), "A", "f1")
assertInvoke(getMethod(b, "t2"), "B", "B$$f2m")
assertInvoke(getMethod(b, "t3"), "B", "<init>")
assertInvoke(getMethod(b, "t4"), "B", "<init>")
@@ -1526,4 +1526,52 @@ class InlinerTest extends BytecodeTesting {
val c :: _ = compileClassesSeparately(codes, extraArgs = compilerArgs)
assertInvoke(getMethod(c, "t"), "p1/Implicits$RichFunction1$", "toRx$extension")
}
+
+ @Test
+ def keepLineNumbersPerCompilationUnit(): Unit = {
+ val code1 =
+ """class A {
+ | def fx(): Unit = ()
+ | @inline final def ma = {
+ | fx()
+ | 1
+ | }
+ |}
+ """.stripMargin
+ val code2 =
+ """class B extends A {
+ | @inline final def mb = {
+ | fx()
+ | 1
+ | }
+ |}
+ |class C extends B {
+ | @inline final def mc = {
+ | fx()
+ | 1
+ | }
+ | def t1 = ma // no lines, not the same source file
+ | def t2 = mb // lines
+ | def t3 = mc // lines
+ |}
+ """.stripMargin
+ notPerRun.foreach(_.clear())
+ val run = compiler.newRun
+ run.compileSources(List(makeSourceFile(code1, "A.scala"), makeSourceFile(code2, "B.scala")))
+ val List(_, _, c) = readAsmClasses(getGeneratedClassfiles(global.settings.outputDirs.getSingleOutput.get))
+ def is(name: String) = getMethod(c, name).instructions.filterNot(_.isInstanceOf[FrameEntry])
+
+ assertSameCode(is("t1"), List(
+ Label(0), LineNumber(12, Label(0)),
+ VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "A", "fx", "()V", false),
+ Op(ICONST_1), Op(IRETURN), Label(6)))
+
+ assertSameCode(is("t2"), List(
+ Label(0), LineNumber(3, Label(0)), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "B", "fx", "()V", false),
+ Label(4), LineNumber(4, Label(4)), Op(ICONST_1), Op(IRETURN), Label(8)))
+
+ assertSameCode(is("t3"), List(
+ Label(0), LineNumber(9, Label(0)), VarOp(ALOAD, 0), Invoke(INVOKEVIRTUAL, "C", "fx", "()V", false),
+ Label(4), LineNumber(10, Label(4)), Op(ICONST_1), Op(IRETURN), Label(8)))
+ }
}
diff --git a/test/junit/scala/tools/testing/BytecodeTesting.scala b/test/junit/scala/tools/testing/BytecodeTesting.scala
index 1a0c1e210a..4ddb6580df 100644
--- a/test/junit/scala/tools/testing/BytecodeTesting.scala
+++ b/test/junit/scala/tools/testing/BytecodeTesting.scala
@@ -29,7 +29,7 @@ class Compiler(val global: Global) {
global.settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None))
}
- private def newRun: global.Run = {
+ def newRun: global.Run = {
global.reporter.reset()
resetOutput()
new global.Run()