fix initialization order of attributes
authorJean Privat <jean@pryen.org>
Thu, 4 Apr 2013 15:52:39 +0000 (11:52 -0400)
committerJean Privat <jean@pryen.org>
Thu, 4 Apr 2013 15:52:39 +0000 (11:52 -0400)
Explicitly use the linearization order.

All engines where broken; quite an exploit.

Reported-by: Nathan Heu <nathan.heu@gmail.com>
Signed-off-by: Jean Privat <jean@pryen.org>

src/abstract_compiler.nit
src/naive_interpreter.nit
src/program.nit
tests/base_attr_init_val_inh.nit [new file with mode: 0644]
tests/sav/base_attr_init_val_inh.res [new file with mode: 0644]

index b5613c6..f6a56fc 100644 (file)
@@ -338,8 +338,9 @@ abstract class AbstractCompiler
        # Generate code that initialize the attributes on a new instance
        fun generate_init_attr(v: VISITOR, recv: RuntimeVariable, mtype: MClassType)
        do
-               for cd in mtype.collect_mclassdefs(self.mainmodule)
-               do
+               var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
+               self.mainmodule.linearize_mclassdefs(cds)
+               for cd in cds do
                        var n = self.modelbuilder.mclassdef2nclassdef[cd]
                        for npropdef in n.n_propdefs do
                                if npropdef isa AAttrPropdef then
@@ -352,8 +353,9 @@ abstract class AbstractCompiler
        # Generate code that check if an attribute is correctly initialized
        fun generate_check_attr(v: VISITOR, recv: RuntimeVariable, mtype: MClassType)
        do
-               for cd in mtype.collect_mclassdefs(self.mainmodule)
-               do
+               var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
+               self.mainmodule.linearize_mclassdefs(cds)
+               for cd in cds do
                        var n = self.modelbuilder.mclassdef2nclassdef[cd]
                        for npropdef in n.n_propdefs do
                                if npropdef isa AAttrPropdef then
index e1ff47b..77f7f0f 100644 (file)
@@ -438,8 +438,9 @@ private class NaiveInterpreter
                if cache.has_key(mtype) then return cache[mtype]
 
                var res = new Array[AAttrPropdef]
-               for cd in mtype.collect_mclassdefs(self.mainmodule)
-               do
+               var cds = mtype.collect_mclassdefs(self.mainmodule).to_a
+               self.mainmodule.linearize_mclassdefs(cds)
+               for cd in cds do
                        var n = self.modelbuilder.mclassdef2nclassdef[cd]
                        for npropdef in n.n_propdefs do
                                if npropdef isa AAttrPropdef then
index 108033f..728b7ce 100644 (file)
@@ -91,16 +91,19 @@ class Program
                                        var iroutine = new IRoutine(iselfa, null)
                                        var icb = new ICodeBuilder(main_module, iroutine)
 
-                                       for g in c.global_properties do
-                                               if not g.intro isa MMAttribute then continue
-                                               var p = c[g]
-                                               var t = p.signature.return_type
-                                               if p isa MMAttribute and t != null then
-                                                       var ir = p.iroutine
-                                                       if ir == null then continue
-                                                       # FIXME: Not compatible with sep compilation
-                                                       var e = icb.inline_routine(ir, iselfa, null).as(not null)
-                                                       icb.stmt(new IAttrWrite(p, iself, e))
+                                       for sc in c.che.linear_extension.reversed do
+                                               for g in sc.global_properties do
+                                                       if g.local_class != sc then continue
+                                                       if not g.intro isa MMAttribute then continue
+                                                       var p = c[g]
+                                                       var t = p.signature.return_type
+                                                       if p isa MMAttribute and t != null then
+                                                               var ir = p.iroutine
+                                                               if ir == null then continue
+                                                               # FIXME: Not compatible with sep compilation
+                                                               var e = icb.inline_routine(ir, iselfa, null).as(not null)
+                                                               icb.stmt(new IAttrWrite(p, iself, e))
+                                                       end
                                                end
                                        end
 
diff --git a/tests/base_attr_init_val_inh.nit b/tests/base_attr_init_val_inh.nit
new file mode 100644 (file)
index 0000000..4e0d487
--- /dev/null
@@ -0,0 +1,45 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+       var a1 = new W(1)
+       var a2: W = a1
+end
+
+class B
+       super A
+       var b1 = new W(2)
+       var b2: W = b1
+       var b3: W = a1
+end
+
+class W
+       var v: Int
+end
+
+var test1 = new A
+test1.a1.v.output
+test1.a2.v.output
+
+'\n'.output
+
+var test2 = new B
+test2.a1.v.output
+test2.a2.v.output
+test2.b1.v.output
+test2.b2.v.output
+test2.b3.v.output
+
diff --git a/tests/sav/base_attr_init_val_inh.res b/tests/sav/base_attr_init_val_inh.res
new file mode 100644 (file)
index 0000000..a34ee90
--- /dev/null
@@ -0,0 +1,8 @@
+1
+1
+
+1
+1
+2
+2
+1