]> code.delx.au - gnu-emacs/commitdiff
Fix emacs-module.c for wide ints
authorEli Zaretskii <eliz@gnu.org>
Tue, 1 Dec 2015 18:34:12 +0000 (20:34 +0200)
committerEli Zaretskii <eliz@gnu.org>
Tue, 1 Dec 2015 18:34:12 +0000 (20:34 +0200)
* src/emacs-module.c (lisp_to_value): Compare the produced value
with the original Lisp object, not with the one potentially
converted into a Lisp_Cons.  Fixes assertion violations when
working with integers larger than fit into a 32-bit value.

* modules/mod-test/test.el (mod-test-sum-test): Add tests for
large integers, to test --with-wide-int.

modules/mod-test/test.el
src/emacs-module.c

index a0abdab49e532358357bf815b57db06e940c1599..eacc6671ead93ce81f5ca18abcc95094ad8d7762 100644 (file)
                  (nth 1 descr))))
     (should (= (nth 2 descr) 3)))
   (should-error (mod-test-sum "1" 2) :type 'wrong-type-argument)
-  (should-error (mod-test-sum 1 "2") :type 'wrong-type-argument))
+  (should-error (mod-test-sum 1 "2") :type 'wrong-type-argument)
+  (should (= (mod-test-sum -1 most-positive-fixnum)
+             (1- most-positive-fixnum)))
+  (should (= (mod-test-sum 1 most-negative-fixnum)
+             (1+ most-negative-fixnum))))
 
 (ert-deftest mod-test-sum-docstring ()
   (should (string= (documentation 'mod-test-sum) "Return A + B")))
index 67e5eab0110892654f7c96ba31d1bd87b387627a..13f2a1dd98f8018f91a7d68ff7cebabcc8a4ddc9 100644 (file)
@@ -880,44 +880,48 @@ value_to_lisp (emacs_value v)
 static emacs_value
 lisp_to_value (Lisp_Object o)
 {
-  EMACS_INT i = XLI (o);
 #ifdef WIDE_EMACS_INT
   /* We need to compress the EMACS_INT into the space of a pointer.
      For most objects, this is just a question of shuffling the tags around.
      But in some cases (e.g. large integers) this can't be done, so we
      should allocate a special object to hold the extra data.  */
+  Lisp_Object orig = o;
   int tag = XTYPE (o);
   switch (tag)
     {
     case_Lisp_Int:
       {
-        EMACS_UINT val = i & VALMASK;
-        if (val <= (SIZE_MAX >> GCTYPEBITS))
+        EMACS_UINT ui = (EMACS_UINT) XINT (o);
+        if (ui <= (SIZE_MAX >> GCTYPEBITS))
           {
-           size_t tv = (size_t)val;
-            emacs_value v = (emacs_value) ((tv << GCTYPEBITS) | tag);
+            uintptr_t uv = (uintptr_t) ui;
+            emacs_value v = (emacs_value) ((uv << GCTYPEBITS) | tag);
             eassert (EQ (value_to_lisp (v), o));
             return v;
           }
         else
-          o = Fcons (o, ltv_mark);
+          {
+            o = Fcons (o, ltv_mark);
+            tag = Lisp_Cons;
+          }
       } /* FALLTHROUGH */
     default:
       {
         void *ptr = XUNTAG (o, tag);
-        if (((size_t)ptr) & ((1 << GCTYPEBITS) - 1))
+        if (((uintptr_t)ptr) & ((1 << GCTYPEBITS) - 1))
           { /* Pointer is not properly aligned!  */
             eassert (!CONSP (o)); /* Cons cells have to always be aligned!  */
             o = Fcons (o, ltv_mark);
             ptr = XUNTAG (o, tag);
           }
-        emacs_value v = (emacs_value)(((size_t) ptr) | tag);
-        eassert (EQ (value_to_lisp (v), o));
+        emacs_value v = (emacs_value) (((uintptr_t) ptr) | tag);
+        eassert (EQ (value_to_lisp (v), orig));
         return v;
       }
     }
 #else
-  emacs_value v = (emacs_value)i;
+  emacs_value v = (emacs_value) XLI (o);
+
   /* Check the assumption made elsewhere that Lisp_Object and emacs_value
      share the same underlying bit representation.  */
   eassert (v == *(emacs_value*)&o);