aboutsummaryrefslogtreecommitdiff
path: root/gcc/cpplex.c
diff options
context:
space:
mode:
authorNeil Booth <neil@daikokuya.demon.co.uk>2002-05-05 23:13:04 +0000
committerNeil Booth <neil@gcc.gnu.org>2002-05-05 23:13:04 +0000
commit639e8b0c74657bde548f374fe887cb2eb7a9ce9c (patch)
tree15ed44a42e459ceafe9e014f17378a1a184f2bc1 /gcc/cpplex.c
parent84ea5bc107f6bfb7efcdec0a2604fc3d3144ec81 (diff)
downloadgcc-639e8b0c74657bde548f374fe887cb2eb7a9ce9c.zip
gcc-639e8b0c74657bde548f374fe887cb2eb7a9ce9c.tar.gz
gcc-639e8b0c74657bde548f374fe887cb2eb7a9ce9c.tar.bz2
cpplex.c (cpp_interpret_charconst): Sign-extend each character.
* 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. From-SVN: r53200
Diffstat (limited to 'gcc/cpplex.c')
-rw-r--r--gcc/cpplex.c49
1 files changed, 22 insertions, 27 deletions
diff --git a/gcc/cpplex.c b/gcc/cpplex.c
index ee34512..d326898 100644
--- a/gcc/cpplex.c
+++ b/gcc/cpplex.c
@@ -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;