[m-rev.] for review: fix bug #158
Peter Wang
novalazy at gmail.com
Thu Aug 19 16:07:56 AEST 2010
Branches: main, 10.04
When a foreign_proc output variable of type `char' is assigned to an
MR_Word variable, it must first be cast to an MR_UnsignedChar to prevent
sign-extension of 8-bit character values. This was documented in
mercury_string.h.
Fixes bug #158.
compiler/llds_out_instr.m:
As above.
tests/hard_coded/Mmakefile:
tests/hard_coded/char_signed.exp:
tests/hard_coded/char_signed.m:
Add test case.
diff --git a/compiler/llds_out_instr.m b/compiler/llds_out_instr.m
index abdc6dc..1df9d9f 100644
--- a/compiler/llds_out_instr.m
+++ b/compiler/llds_out_instr.m
@@ -1951,17 +1951,26 @@ output_foreign_proc_output(Info, Output, !IO) :-
MaybeForeignType = no,
output_lval_as_word(Info, Lval, !IO),
io.write_string(" = ", !IO),
- (
- OrigType = builtin_type(builtin_type_string)
- ->
- output_llds_type_cast(lt_word, !IO),
- io.write_string(VarName, !IO)
- ;
- OrigType = builtin_type(builtin_type_float)
- ->
- io.write_string("MR_float_to_word(", !IO),
- io.write_string(VarName, !IO),
- io.write_string(")", !IO)
+ ( OrigType = builtin_type(BuiltinType) ->
+ (
+ BuiltinType = builtin_type_string,
+ output_llds_type_cast(lt_word, !IO),
+ io.write_string(VarName, !IO)
+ ;
+ BuiltinType = builtin_type_float,
+ io.write_string("MR_float_to_word(", !IO),
+ io.write_string(VarName, !IO),
+ io.write_string(")", !IO)
+ ;
+ BuiltinType = builtin_type_char,
+ % Characters must be cast to MR_UnsignedChar to
+ % prevent sign-extension.
+ io.write_string("(MR_UnsignedChar) ", !IO),
+ io.write_string(VarName, !IO)
+ ;
+ BuiltinType = builtin_type_int,
+ io.write_string(VarName, !IO)
+ )
;
io.write_string(VarName, !IO)
)
diff --git a/tests/hard_coded/Mmakefile b/tests/hard_coded/Mmakefile
index 1cf78d3..ddee18d 100644
--- a/tests/hard_coded/Mmakefile
+++ b/tests/hard_coded/Mmakefile
@@ -21,6 +21,7 @@ ORDINARY_PROGS= \
cc_and_non_cc_test \
cc_multi_bug \
cc_nondet_disj \
+ char_signed \
checked_nondet_tailcall \
checked_nondet_tailcall_noinline \
closure_extension \
diff --git a/tests/hard_coded/char_signed.exp b/tests/hard_coded/char_signed.exp
new file mode 100644
index 0000000..ad94b65
--- /dev/null
+++ b/tests/hard_coded/char_signed.exp
@@ -0,0 +1,4 @@
+unify succeed
+'A' < 0xFF
+0xFF >= 'A'
+'A' < 0xFF
diff --git a/tests/hard_coded/char_signed.m b/tests/hard_coded/char_signed.m
new file mode 100644
index 0000000..7700a6a
--- /dev/null
+++ b/tests/hard_coded/char_signed.m
@@ -0,0 +1,43 @@
+% Bug 158 and related issues with 8-bit characters due to MR_Char being
+% signed (potentially).
+
+:- module char_signed.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module char.
+:- import_module int.
+
+main(!IO) :-
+ ( char.det_from_int(255) = '\xFF\' ->
+ io.write_string("unify succeed\n", !IO)
+ ;
+ io.write_string("unify fail\n", !IO)
+ ),
+ ( aa @< '\xFF\' ->
+ io.write_string("'A' < 0xFF\n", !IO)
+ ;
+ io.write_string("'A' >= 0xFF (wrong)\n", !IO)
+ ),
+ ( '\xFF\' @< aa ->
+ io.write_string("0xFF < 'A' (wrong)\n", !IO)
+ ;
+ io.write_string("0xFF >= 'A'\n", !IO)
+ ),
+ ( char.to_int('A') < char.to_int('\xFF\') : int ->
+ io.write_string("'A' < 0xFF\n", !IO)
+ ;
+ io.write_string("'A' >= 0xFF (wrong)\n", !IO)
+ ).
+
+:- func aa = char.
+:- pragma no_inline(aa/0).
+
+aa = char.det_from_int(65).
+
+% vim: ft=mercury ts=8 sts=4 sw=4 et
--------------------------------------------------------------------------
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