[m-rev.] diff: fix mantis bug 109

Zoltan Somogyi zs at csse.unimelb.edu.au
Tue Sep 14 12:22:17 AEST 2010


Fix Mantis bug #109.

compiler/add_heap_ops.m:
	Fix the bug. The bug was that this pass tried to record the heap
	pointer at the start of the nth disjunct, even in cases where
	there were no following disjuncts at whose starts that saved
	heap pointer could be restored (to recover the memory allocated
	by the nth disjunct). The symptom was a disjunction with only
	one disjunct, but the problem was a simple semantic one. The fix
	is simply to say that we won't record the heap pointer before the nth
	disjunct unless disjunct n+1 exists.
	
	Improve the generated HLDS in another way as well: wrap the appropriate
	kind of promise_purity scope around the transformed code (which uses
	impure primitives).

tests/valid/bug109.m:
	Add the regression test for this bug.

tests/valid/Mmakefile:
tests/valid/Mercury.options:
	Enable the test case.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/extra
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/extra
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/doc
cvs diff: Diffing boehm_gc/libatomic_ops/src
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/armcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops/tests
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/m4
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_heap_ops.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_heap_ops.m,v
retrieving revision 1.43
diff -u -b -r1.43 add_heap_ops.m
--- compiler/add_heap_ops.m	10 Sep 2010 05:14:56 -0000	1.43
+++ compiler/add_heap_ops.m	13 Sep 2010 04:03:07 -0000
@@ -12,14 +12,12 @@
 % This module is an HLDS-to-HLDS transformation that inserts code to
 % handle heap reclamation on backtracking, by saving and restoring
 % the values of the heap pointer.
-% The transformation involves adding calls to impure
-% predicates defined in library/private_builtin.m, which in turn call
-% the MR_mark_hp() and MR_restore_hp() macros defined in
-% runtime/mercury_heap.h.
+% The transformation involves adding calls to impure predicates defined in
+% library/private_builtin.m, which in turn call the MR_mark_hp() and
+% MR_restore_hp() macros defined in runtime/mercury_heap.h.
 %
-% This pass is currently only used for the MLDS back-end.
-% For some reason (perhaps efficiency?? or more likely just historical?),
-% the LLDS back-end inserts the heap operations as it is generating
+% This pass is currently only used for the MLDS back-end. For historical
+% reasons, the LLDS back-end inserts the heap operations as it is generating
 % LLDS code, rather than via an HLDS to HLDS transformation.
 %
 % This module is very similar to add_trail_ops.m.
@@ -68,12 +66,12 @@
 %-----------------------------------------------------------------------------%
 
     % As we traverse the goal, we add new variables to hold the saved values
-    % of the heap pointer. So we need to thread a varset and a vartypes mapping
-    % through, to record the names and types of the new variables.
+    % of the heap pointer. So we need the varset and the vartypes map to record
+    % the names and types of the new variables.
     %
     % We also keep the module_info around, so that we can use the predicate
     % table that it contains to lookup the pred_ids for the builtin procedures
-    % that we insert calls to. We do not update the module_info as we're
+    % that we insert calls to. We do not update the module_info as we are
     % traversing the goal.
     %
 :- type heap_ops_info
@@ -141,9 +139,13 @@
                     !Info),
                 disj_add_heap_ops(Disjuncts0, Disjuncts, is_first_disjunct,
                     yes(SavedHeapPointerVar), GoalInfo0, !Info),
-                GoalExpr = conj(plain_conj,
-                    [MarkHeapPointerGoal,
-                        hlds_goal(disj(Disjuncts), GoalInfo0)])
+                DisjGoalExpr = disj(Disjuncts),
+                DisjGoal = hlds_goal(DisjGoalExpr, GoalInfo0),
+                ConjGoalExpr = conj(plain_conj,
+                    [MarkHeapPointerGoal, DisjGoal]),
+                ConjGoal = hlds_goal(ConjGoalExpr, GoalInfo0),
+                Purity0 = goal_info_get_purity(GoalInfo0),
+                GoalExpr = scope(promise_purity(Purity0), ConjGoal)
             ;
                 disj_add_heap_ops(Disjuncts0, Disjuncts, is_first_disjunct,
                     no, GoalInfo0, !Info),
@@ -197,14 +199,14 @@
         GoalExpr = scope(Reason, SubGoal),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
-        GoalExpr0 = if_then_else(Vars, Cond0, Then0, Else0),
-        goal_add_heap_ops(Cond0, Cond, !Info),
-        goal_add_heap_ops(Then0, Then, !Info),
-        goal_add_heap_ops(Else0, Else1, !Info),
+        GoalExpr0 = if_then_else(Vars, CondGoal0, ThenGoal0, ElseGoal0),
+        goal_add_heap_ops(CondGoal0, CondGoal, !Info),
+        goal_add_heap_ops(ThenGoal0, ThenGoal, !Info),
+        goal_add_heap_ops(ElseGoal0, ElseGoal1, !Info),
 
         % If the condition can allocate heap space, save the heap pointer
         % so that we can restore it if the condition fails.
-        ( goal_may_allocate_heap(Cond0) ->
+        ( goal_may_allocate_heap(CondGoal0) ->
             new_saved_hp_var(SavedHeapPointerVar, !Info),
             Context = goal_info_get_context(GoalInfo0),
             gen_mark_hp(SavedHeapPointerVar, Context, MarkHeapPointerGoal,
@@ -214,15 +216,18 @@
             % at the start of the Else branch.
             gen_restore_hp(SavedHeapPointerVar, Context,
                 RestoreHeapPointerGoal, !Info),
-            Else1 = hlds_goal(_, Else1GoalInfo),
-            Else = hlds_goal(
-                conj(plain_conj, [RestoreHeapPointerGoal, Else1]),
-                Else1GoalInfo),
-            IfThenElseExpr = if_then_else(Vars, Cond, Then, Else),
-            IfThenElse = hlds_goal(IfThenElseExpr, GoalInfo0),
-            GoalExpr = conj(plain_conj, [MarkHeapPointerGoal, IfThenElse])
+            ElseGoal1 = hlds_goal(_, ElseGoal1Info),
+            ElseGoalExpr = conj(plain_conj,
+                [RestoreHeapPointerGoal, ElseGoal1]),
+            ElseGoal = hlds_goal(ElseGoalExpr, ElseGoal1Info),
+            ITEGoalExpr = if_then_else(Vars, CondGoal, ThenGoal, ElseGoal),
+            ITEGoal = hlds_goal(ITEGoalExpr, GoalInfo0),
+            ConjGoalExpr = conj(plain_conj, [MarkHeapPointerGoal, ITEGoal]),
+            ConjGoal = hlds_goal(ConjGoalExpr, GoalInfo0),
+            Purity0 = goal_info_get_purity(GoalInfo0),
+            GoalExpr = scope(promise_purity(Purity0), ConjGoal)
         ;
-            GoalExpr = if_then_else(Vars, Cond, Then, Else1)
+            GoalExpr = if_then_else(Vars, CondGoal, ThenGoal, ElseGoal1)
         ),
         Goal = hlds_goal(GoalExpr, GoalInfo0)
     ;
@@ -270,11 +275,15 @@
         Goal = Goal1
     ),
 
-    % Save the heap pointer, if we haven't already done so, and if this
-    % disjunct might allocate heap space.
+    % Save the heap pointer,
+    % - if we haven't already done so,
+    % - if this disjunct might allocate heap space, and
+    % - if a next disjunct exists to give us a chance to recover
+    %   that heap space.
     (
         MaybeSavedHeapPointerVar = no,
-        goal_may_allocate_heap(Goal)
+        goal_may_allocate_heap(Goal),
+        Goals0 = [_ | _]
     ->
         % Generate code to save the heap pointer.
         new_saved_hp_var(SavedHeapPointerVar, !Info),
@@ -285,12 +294,15 @@
             yes(SavedHeapPointerVar), DisjGoalInfo, !Info),
         % Put this disjunct and the remaining disjuncts in a nested
         % disjunction, so that the heap pointer variable can scope over
-        % these disjuncts.
-        Disj = hlds_goal(disj([Goal | Goals1]), DisjGoalInfo),
-        DisjGoal = hlds_goal(
-            conj(plain_conj, [MarkHeapPointerGoal, Disj]),
-            DisjGoalInfo),
-        DisjGoals = [DisjGoal]
+        % these disjuncts. (This wouldn't work if Goals0 were [].)
+        InnerDisjGoalExpr = disj([Goal | Goals1]),
+        InnerDisjGoal = hlds_goal(InnerDisjGoalExpr, DisjGoalInfo),
+        ConjGoalExpr = conj(plain_conj, [MarkHeapPointerGoal, InnerDisjGoal]),
+        ConjGoal = hlds_goal(ConjGoalExpr, DisjGoalInfo),
+        Purity = goal_info_get_purity(DisjGoalInfo),
+        ScopeGoalExpr = scope(promise_purity(Purity), ConjGoal),
+        ScopeGoal = hlds_goal(ScopeGoalExpr, DisjGoalInfo),
+        DisjGoals = [ScopeGoal]
     ;
         % Just recursively handle the remaining disjuncts.
         disj_add_heap_ops(Goals0, Goals, is_not_first_disjunct,
cvs diff: Diffing compiler/notes
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_cairo
cvs diff: Diffing extras/graphics/mercury_cairo/samples
cvs diff: Diffing extras/graphics/mercury_cairo/samples/data
cvs diff: Diffing extras/graphics/mercury_cairo/tutorial
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/monte
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/java_interface
cvs diff: Diffing samples/java_interface/java_calls_mercury
cvs diff: Diffing samples/java_interface/mercury_calls_java
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
Index: tests/valid/Mercury.options
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/valid/Mercury.options,v
retrieving revision 1.68
diff -u -b -r1.68 Mercury.options
--- tests/valid/Mercury.options	10 May 2010 05:02:27 -0000	1.68
+++ tests/valid/Mercury.options	13 Sep 2010 04:18:45 -0000
@@ -22,13 +22,15 @@
 GRADEFLAGS-foreign_type_spec	=  --grade il
 GRADEFLAGS-foreign_type_spec.foreign_type = --grade il
 
+# The bug that this test looks for exists only in MLDS grades without any gc.
+GRADEFLAGS-bug109		= --grade hlc
+
 # The following test cases check for bugs that can only occur in the
 # presence of automatic solver type intialisation.
 MCFLAGS-fz_conf                 = --solver-type-auto-init
 MCFLAGS-solver_type_bug_2       = --solver-type-auto-init
 MCFLAGS-solver_type_mutable_bug = --solver-type-auto-init
 
-
 MCFLAGS-ambig_confuse1      = --type-check-constraints
 MCFLAGS-ambig_confuse2      = --type-check-constraints
 MCFLAGS-ambig_confuse3      = --type-check-constraints
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.241
diff -u -b -r1.241 Mmakefile
--- tests/valid/Mmakefile	18 Aug 2010 00:58:55 -0000	1.241
+++ tests/valid/Mmakefile	13 Sep 2010 04:15:10 -0000
@@ -59,6 +59,10 @@
 	csharp_hello \
 	foreign_type_spec
 
+	# Tests for which we should only produce a `.c' file.
+C_PROGS = \
+	bug109
+
 OTHER_PROGS= \
 	any_inst_merge \
 	any_matches_bound \
@@ -312,7 +316,6 @@
 	ambig_pred_3 \
  	ambiguity_stress_test
 
-
 # XXX The type checker can't handle the following test cases yet,
 # unless constraint-based typechecking is used:
 #	ambiguity_stress_test
@@ -409,9 +412,9 @@
 endif
 
 ifneq "$(findstring tsw,$(GRADE))$(findstring tsc,$(GRADE))" ""
-	PROGS = $(OBJ_PROGS)
+	PROGS = $(OBJ_PROGS) $(C_PROGS)
 else
-	PROGS = $(OBJ_PROGS) $(IL_PROGS)
+	PROGS = $(OBJ_PROGS) $(C_PROGS) $(IL_PROGS)
 endif
 
 # `mmc --make' doesn't expect subdirectories to appear in targets.
@@ -427,7 +430,6 @@
 CLASSES_SUBDIR=$(classes_subdir)
 endif
 
-
 ifeq ($(findstring il,$(GRADE)),il)
 	TARGET_OBJ_EXT=dll
 	TARGET_OBJ_SUBDIR=$(DLLS_SUBDIR)
@@ -456,7 +458,7 @@
 TESTS_DIR = ..
 include $(TESTS_DIR)/Mmake.common
 
-# When compiling using the installed libraries, setting GRADEFLAGS may
+# When compiling using the installed libraries, setting GRADEFLAGS
 # may cause mgnuc to look for the `.mih' files for a non-installed grade.
 # test_mercury runs the tests using the installed libraries, so GRADEFLAGS
 # won't be set, but test_mercury runs the tests in at least one `.tr' grade
@@ -475,6 +477,8 @@
 
 $(OBJ_PROGS:%=%.runtest): %.runtest: %.$(TARGET_OBJ_EXT) ;
 
+$(C_PROGS:%=%.runtest): %.runtest: %.c ;
+
 $(IL_PROGS:%=%.runtest): %.runtest: %.il ;
 
 #-----------------------------------------------------------------------------#
Index: tests/valid/bug109.m
===================================================================
RCS file: tests/valid/bug109.m
diff -N tests/valid/bug109.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/valid/bug109.m	14 Sep 2010 02:20:06 -0000
@@ -0,0 +1,48 @@
+%-----------------------------------------------------------------------------%
+% vim: ts=4 sw=4 et tw=0 wm=0 ft=mercury
+%-----------------------------------------------------------------------------%
+%
+% This test case is a regression test for Mantis bug #109. Its code was derived
+% from the function bits/3 in library/bitmap.m.
+%
+% In high-level C nogc grades, e.g. hlc, hl, hlc_nest, or hl_nest, this
+% program used to cause the compiler to abort with:
+%
+%     Software Error: ml_disj_gen.m: Unexpected: ml_gen_disj: single disjunct
+%
+% The problem was a bug in add_heap_ops.m, fixed 14 Sep 2010.
+%
+%-----------------------------------------------------------------------------%
+
+:- module bug109.
+:- interface.
+
+%-----------------------------------------------------------------------------%
+
+:- func bits(int) = int.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int.
+
+%-----------------------------------------------------------------------------%
+
+bits(NumBits) = Result :-
+   ( if
+        (
+            NumBits < 0
+        ;
+            X = int.bits_per_int,
+            NumBits > X
+        )
+      then
+        Result = 10
+      else
+        Result = 42
+    ).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list