OSDN Git Service

* cpplex.c (cpp_interpret_charconst): Sign-extend each
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 May 2002 23:13:04 +0000 (23:13 +0000)
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 May 2002 23:13:04 +0000 (23:13 +0000)
character.  Don't ignore excess characters.  Treat
multicharacter character constants as signed.
(cpp_parse_escape): Clarify diagnostic.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53200 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cpplex.c

index fc401c2..8d2de30 100644 (file)
@@ -1,3 +1,10 @@
+2002-05-06  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * cpplex.c (cpp_interpret_charconst): Sign-extend each
+       character.  Don't ignore excess characters.  Treat
+       multicharacter character constants as signed.
+       (cpp_parse_escape): Clarify diagnostic.
+
 2002-05-05  Jakub Jelinek  <jakub@redhat.com>
 
        * config/sparc/sparc.md (ashlsi3): If shift count is const1_rtx,
index ee34512..d326898 100644 (file)
@@ -1847,7 +1847,7 @@ cpp_parse_escape (pfile, pstr, limit, wide)
 
   if (c > mask)
     {
-      cpp_error (pfile, DL_PEDWARN, "escape sequence out of range for type");
+      cpp_error (pfile, DL_PEDWARN, "escape sequence out of range for its type");
       c &= mask;
     }
 
@@ -1871,7 +1871,7 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp)
   const unsigned char *str = token->val.str.text;
   const unsigned char *limit = str + token->val.str.len;
   unsigned int chars_seen = 0;
-  unsigned int width, max_chars;
+  size_t width, max_chars;
   cppchar_t c, mask, result = 0;
   bool unsigned_p;
 
@@ -1928,36 +1928,31 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp)
        c = MAP_CHARACTER (c);
 #endif
       
-      /* Merge character into result; ignore excess chars.  */
-      if (++chars_seen <= max_chars)
-       {
-         if (width < BITS_PER_CPPCHAR_T)
-           result = (result << width) | (c & mask);
-         else
-           result = c;
-       }
+      chars_seen++;
+
+      /* Sign-extend the character, scale result, and add the two.  */
+      if (!unsigned_p && (c & (1 << (width - 1))))
+       c |= ~mask;
+      if (width < BITS_PER_CPPCHAR_T)
+       result = (result << width) + c;
+      else
+       result = c;
     }
 
   if (chars_seen == 0)
     cpp_error (pfile, DL_ERROR, "empty character constant");
-  else if (chars_seen > max_chars)
+  else if (chars_seen > 1)
     {
-      chars_seen = max_chars;
-      cpp_error (pfile, DL_WARNING, "character constant too long");
-    }
-  else if (chars_seen > 1 && warn_multi)
-    cpp_error (pfile, DL_WARNING, "multi-character character constant");
-
-  /* If relevant type is signed, sign-extend the constant.  */
-  if (chars_seen)
-    {
-      unsigned int nbits = chars_seen * width;
-
-      mask = (cppchar_t) ~0 >> (BITS_PER_CPPCHAR_T - nbits);
-      if (unsigned_p || ((result >> (nbits - 1)) & 1) == 0)
-       result &= mask;
-      else
-       result |= ~mask;
+      /* Multichar charconsts are of type int and therefore signed.  */
+      unsigned_p = 0;
+      if (chars_seen > max_chars)
+       {
+         chars_seen = max_chars;
+         cpp_error (pfile, DL_WARNING,
+                    "character constant too long for its type");
+       }
+      else if (warn_multi)
+       cpp_error (pfile, DL_WARNING, "multi-character character constant");
     }
 
   *pchars_seen = chars_seen;