aboutsummaryrefslogtreecommitdiff
path: root/gcc/cpplex.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cpplex.c')
-rw-r--r--gcc/cpplex.c25
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;