diff options
Diffstat (limited to 'gcc/cpplex.c')
-rw-r--r-- | gcc/cpplex.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/gcc/cpplex.c b/gcc/cpplex.c index d326898..a9f1494 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -1861,10 +1861,9 @@ cpp_parse_escape (pfile, pstr, limit, wide) characters seen, and UNSIGNEDP to a variable that indicates whether the result has signed type. */ cppchar_t -cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp) +cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp) cpp_reader *pfile; const cpp_token *token; - int warn_multi; unsigned int *pchars_seen; int *unsignedp; { @@ -1930,11 +1929,10 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp) chars_seen++; - /* Sign-extend the character, scale result, and add the two. */ - if (!unsigned_p && (c & (1 << (width - 1)))) - c |= ~mask; + /* Truncate the character, scale the result and merge the two. */ + c &= mask; if (width < BITS_PER_CPPCHAR_T) - result = (result << width) + c; + result = (result << width) | c; else result = c; } @@ -1945,16 +1943,29 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp) { /* 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) + else if (CPP_OPTION (pfile, warn_multichar)) cpp_error (pfile, DL_WARNING, "multi-character character constant"); } + /* Sign-extend the constant. */ + if (!unsigned_p) + { + size_t precision = width; + + if (chars_seen > 1) + precision *= max_chars; + if (precision < BITS_PER_CPPCHAR_T + && (result & ((cppchar_t) 1 << (precision - 1)))) + result |= ~(((cppchar_t) 1 << precision) - 1); + } + *pchars_seen = chars_seen; *unsignedp = unsigned_p; return result; |