summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacques Garrigue <garrigue at math.nagoya-u.ac.jp>2012-06-01 04:47:14 +0000
committerJacques Garrigue <garrigue at math.nagoya-u.ac.jp>2012-06-01 04:47:14 +0000
commita430934c06bf4737d963b43da69b1d5203dc20bf (patch)
treeddf53a58e1e575568f9359c4071454b90d04a2b6
parent493e57678b9e378a7c18a6e2dc8673191199e86f (diff)
Fix PR#5291
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@12531 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--Changes1
-rw-r--r--bytecomp/translclass.ml18
-rw-r--r--testsuite/tests/typing-objects/Tests.ml7
-rw-r--r--testsuite/tests/typing-objects/Tests.ml.principal.reference8
-rw-r--r--testsuite/tests/typing-objects/Tests.ml.reference8
5 files changed, 34 insertions, 8 deletions
diff --git a/Changes b/Changes
index 84853deca..8eb21be09 100644
--- a/Changes
+++ b/Changes
@@ -98,6 +98,7 @@ Bug Fixes:
- PR#5211: updated Genlex documentation to state that camlp4 is mandatory for
'parser' keyword and associated notation
- PR#5238, PR#5277: Sys_error when getting error location
+- PR#5291: undetected loop in class initialization
- PR#5295: OS threads: problem with caml_c_thread_unregister()
- PR#5301: camlp4r and exception equal to another one with parameters
- PR#5305: prevent ocamlbuild from complaining about links to _build/
diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml
index e4b415376..a5116f629 100644
--- a/bytecomp/translclass.ml
+++ b/bytecomp/translclass.ml
@@ -362,11 +362,15 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
cl_init))
end
-let rec build_class_lets cl =
+let rec build_class_lets cl ids =
match cl.cl_desc with
- Tcl_let (rec_flag, defs, vals, cl) ->
- let env, wrap = build_class_lets cl in
- (env, fun x -> Translcore.transl_let rec_flag defs (wrap x))
+ Tcl_let (rec_flag, defs, vals, cl') ->
+ let env, wrap = build_class_lets cl' [] in
+ (env, fun x ->
+ let lam = Translcore.transl_let rec_flag defs (wrap x) in
+ (* Check recursion in toplevel let-definitions *)
+ if ids = [] || Translcore.check_recursive_lambda ids lam then lam
+ else raise(Error(cl.cl_loc, Illegal_class_expr)))
| _ ->
(cl.cl_env, fun x -> x)
@@ -595,7 +599,7 @@ let transl_class ids cl_id pub_meths cl vflag =
let tables = Ident.create (Ident.name cl_id ^ "_tables") in
let (top_env, req) = oo_add_class tables in
let top = not req in
- let cl_env, llets = build_class_lets cl in
+ let cl_env, llets = build_class_lets cl ids in
let new_ids = if top then [] else Env.diff top_env cl_env in
let env2 = Ident.create "env" in
let meth_ids = get_class_meths cl in
@@ -662,8 +666,6 @@ let transl_class ids cl_id pub_meths cl vflag =
let cla = Ident.create "class" in
let (inh_init, obj_init) =
build_object_init_0 cla [] cl copy_env subst_env top ids in
- if not (Translcore.check_recursive_lambda ids obj_init) then
- raise(Error(cl.cl_loc, Illegal_class_expr));
let inh_init' = List.rev inh_init in
let (inh_init', cl_init) =
build_class_init cla true ([],[]) inh_init' obj_init msubst top cl
@@ -817,7 +819,7 @@ open Format
let report_error ppf = function
| Illegal_class_expr ->
- fprintf ppf "This kind of class expression is not allowed"
+ fprintf ppf "This kind of recursive class expression is not allowed"
| Tags (lab1, lab2) ->
fprintf ppf "Method labels `%s' and `%s' are incompatible.@ %s"
lab1 lab2 "Change one of them."
diff --git a/testsuite/tests/typing-objects/Tests.ml b/testsuite/tests/typing-objects/Tests.ml
index c7a5cb3d1..759f5d955 100644
--- a/testsuite/tests/typing-objects/Tests.ml
+++ b/testsuite/tests/typing-objects/Tests.ml
@@ -325,3 +325,10 @@ let o = object val x = 33 val y = 44 method m = x end in
let o' : <m:int> = Marshal.from_string s 0 in
let o'' : <m:int> = Marshal.from_string s 0 in
(Oo.id o, Oo.id o', Oo.id o'', o#m, o'#m);;
+
+(* Recursion (cf. PR#5291) *)
+
+class a = let _ = new b in object end
+and b = let _ = new a in object end;;
+
+class a = let _ = new a in object end;;
diff --git a/testsuite/tests/typing-objects/Tests.ml.principal.reference b/testsuite/tests/typing-objects/Tests.ml.principal.reference
index 34a5071d7..ff3980e26 100644
--- a/testsuite/tests/typing-objects/Tests.ml.principal.reference
+++ b/testsuite/tests/typing-objects/Tests.ml.principal.reference
@@ -299,4 +299,12 @@ Warning 10: this expression should have type unit.
# - : int * int * int = (18, 19, 20)
# - : int * int * int * int * int = (21, 22, 23, 33, 33)
# - : int * int * int * int * int = (24, 25, 26, 33, 33)
+# Characters 42-69:
+ class a = let _ = new b in object end
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of recursive class expression is not allowed
+# Characters 11-38:
+ class a = let _ = new a in object end;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of recursive class expression is not allowed
#
diff --git a/testsuite/tests/typing-objects/Tests.ml.reference b/testsuite/tests/typing-objects/Tests.ml.reference
index 45130d58c..098096597 100644
--- a/testsuite/tests/typing-objects/Tests.ml.reference
+++ b/testsuite/tests/typing-objects/Tests.ml.reference
@@ -298,4 +298,12 @@ Warning 10: this expression should have type unit.
# - : int * int * int = (18, 19, 20)
# - : int * int * int * int * int = (21, 22, 23, 33, 33)
# - : int * int * int * int * int = (24, 25, 26, 33, 33)
+# Characters 42-69:
+ class a = let _ = new b in object end
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of recursive class expression is not allowed
+# Characters 11-38:
+ class a = let _ = new a in object end;;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Error: This kind of recursive class expression is not allowed
#