%---------------------------------------------------------------------------% % vim: ts=4 sw=4 et ft=mercury %---------------------------------------------------------------------------% % % This is a regression test for a code generation bug, fixed % on 16 november 1999. % % The bug was that if the failure continuation was a known address, % the code in code_info.m for implementing commits assumed that the % redoip slot of the top nondet stack frame had this address in it, % and that therefore it could override this slot without remembering % what was originally in it. % % The determinism declarations of foo and bar are intentionally too loose; % the bug does not reveal itself, even if it exists, with the correct, tight % determinism declarations. The test for the bug also requires compilation % with inlining turned off. :- module redoip_clobber. :- interface. :- import_module io. :- pred main(io::di, io::uo) is det. :- implementation. :- import_module int. :- import_module std_util. :- pred foo(int). :- mode foo(out) is nondet. foo(X) :- bar(X), fail. foo(X) :- X = 2. :- pred bar(int). :- mode bar(out) is nondet. bar(X) :- X = 1. :- pred use(int). :- mode use(in) is semidet. :- pragma foreign_proc("C", use(X::in), [will_not_call_mercury, promise_pure], " /* ** To exhibit the bug, this predicate needs only to fail. ** However, the symptom of the bug is an infinite loop. ** To detect the presence of the bug in finite time, ** we abort execution if this code is executed too many times. ** ** We mention X here to shut up a warning. */ static int counter = 0; if (++counter > 100) { MR_fatal_error(""the bug is back""); } SUCCESS_INDICATOR = MR_FALSE; "). :- pragma foreign_proc("C#", use(_X::in), [will_not_call_mercury, promise_pure], " SUCCESS_INDICATOR = false; "). :- pragma foreign_proc("Java", use(_X::in), [will_not_call_mercury, promise_pure], " SUCCESS_INDICATOR = false; "). main(!IO) :- ( if foo(X), use(X) then io.write_string("Succeeded.\n", !IO) else io.write_string("Failed.\n", !IO) ).