aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/CheckReentrant.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-07-01 15:28:11 +0200
committerMartin Odersky <odersky@gmail.com>2015-07-06 17:46:44 +0200
commit64f65182f6e4f80b03d45923e02441dafe0755b4 (patch)
tree68301908a5ce6513b43a9778a1f41b8e48bdbadf /src/dotty/tools/dotc/transform/CheckReentrant.scala
parent70f18eb4aa5aff64aa8571c16026c456bc1db5fc (diff)
downloaddotty-64f65182f6e4f80b03d45923e02441dafe0755b4.tar.gz
dotty-64f65182f6e4f80b03d45923e02441dafe0755b4.tar.bz2
dotty-64f65182f6e4f80b03d45923e02441dafe0755b4.zip
Add reentrancy checking
New miniphase CheckRentrant verifies that compiled program is without vars accessible through global roots if -Ycheck-reentrant option is set. Known shortcoming: Array elements are currently not considered as vars. This is because in many programs arrays are used as an efficient container for immutable fields.
Diffstat (limited to 'src/dotty/tools/dotc/transform/CheckReentrant.scala')
-rw-r--r--src/dotty/tools/dotc/transform/CheckReentrant.scala85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/transform/CheckReentrant.scala b/src/dotty/tools/dotc/transform/CheckReentrant.scala
new file mode 100644
index 000000000..aff8a1e7b
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/CheckReentrant.scala
@@ -0,0 +1,85 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import Names._
+import dotty.tools.dotc.transform.TreeTransforms.{AnnotationTransformer, TransformerInfo, MiniPhaseTransform, TreeTransformer}
+import ast.Trees._
+import Flags._
+import Types._
+import Constants.Constant
+import Contexts.Context
+import Symbols._
+import SymDenotations._
+import Decorators._
+import dotty.tools.dotc.core.Annotations.ConcreteAnnotation
+import dotty.tools.dotc.core.Denotations.SingleDenotation
+import scala.collection.mutable
+import DenotTransformers._
+import typer.Checking
+import Names.Name
+import NameOps._
+import StdNames._
+import util.CtxLazy
+
+
+/** The first tree transform
+ * - ensures there are companion objects for all classes except module classes
+ * - eliminates some kinds of trees: Imports, NamedArgs
+ * - stubs out native methods
+ */
+class CheckReentrant extends MiniPhaseTransform { thisTransformer =>
+ import ast.tpd._
+
+ override def phaseName = "checkReentrant"
+
+ def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp
+
+ private var shared: Set[Symbol] = Set()
+
+ private var seen: Set[ClassSymbol] = Set()
+
+ private var indent: Int = 0
+
+ private val sharableAnnot = new CtxLazy(implicit ctx =>
+ ctx.requiredClass("dotty.tools.sharable"))
+ private val unsharedAnnot = new CtxLazy(implicit ctx =>
+ ctx.requiredClass("dotty.tools.unshared"))
+
+ def isIgnored(sym: Symbol)(implicit ctx: Context) =
+ sym.hasAnnotation(sharableAnnot()) ||
+ sym.hasAnnotation(unsharedAnnot())
+
+ def scanning(sym: Symbol)(op: => Unit)(implicit ctx: Context): Unit = {
+ println(i"${" " * indent}scanning $sym")
+ indent += 1
+ try op
+ finally indent -= 1
+ }
+
+ def addVars(cls: ClassSymbol)(implicit ctx: Context): Unit = {
+ if (!seen.contains(cls) && !isIgnored(cls)) {
+ seen += cls
+ scanning(cls) {
+ for (sym <- cls.classInfo.decls)
+ if (sym.isTerm && !sym.isSetter && !isIgnored(sym))
+ if (sym.is(Mutable)) {
+ println(i"GLOBAL ${sym.showLocated}: ${sym.info} <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
+ shared += sym
+ } else if (!sym.is(Method) || sym.is(Accessor | ParamAccessor)) {
+ scanning(sym) {
+ sym.info.widenExpr.classSymbols.foreach(addVars)
+ }
+ }
+ for (parent <- cls.classInfo.classParents)
+ addVars(parent.symbol.asClass)
+ }
+ }
+ }
+
+ override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ if (ctx.settings.YcheckReentrant.value && tree.symbol.owner.isStaticOwner)
+ addVars(tree.symbol.owner.asClass)
+ tree
+ }
+} \ No newline at end of file