diff options
author | neil <neil@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-08 21:02:31 +0000 |
---|---|---|
committer | neil <neil@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-05-08 21:02:31 +0000 |
commit | 2798f07c7bedd317fa7b596c071f0b2672d439e8 (patch) | |
tree | dcf24c4e35c90d6be02f200980d40c51523db0ad /gcc | |
parent | 053d448f60b0858472a312faa1362eb2fe5d5044 (diff) | |
download | gcc-2798f07c7bedd317fa7b596c071f0b2672d439e8.tar.gz |
* cpplex.c (cpp_interpret_charconst): Truncate as well as
sign-extend.
doc:
* cpp.texi: Clarify multichar charconst valuation.
testsuite:
* gcc.dg/cpp/charconst-4.c: More tests.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@53301 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cpplex.c | 20 | ||||
-rw-r--r-- | gcc/doc/cpp.texi | 22 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cpp/charconst-4.c | 50 |
5 files changed, 84 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c8321e9a642..3b3bede67ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2002-05-08 Neil Booth <neil@daikokuya.demon.co.uk> + + * cpplex.c (cpp_interpret_charconst): Truncate as well as + sign-extend. +doc: + * cpp.texi: Clarify multichar charconst valuation. + 2002-05-08 Mark Mitchell <mark@codesourcery.com> * doc/invoke.texi: Document -mwindiss option. diff --git a/gcc/cpplex.c b/gcc/cpplex.c index 39afc5905a9..bba6f074730 100644 --- a/gcc/cpplex.c +++ b/gcc/cpplex.c @@ -1954,16 +1954,18 @@ cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp) cpp_error (pfile, DL_WARNING, "multi-character character constant"); } - /* Sign-extend the constant. */ - if (!unsigned_p) + /* Sign-extend or truncate the constant to cppchar_t. The value is + in WIDTH bits, but for multi-char charconsts it's value is the + full target type's width. */ + if (chars_seen > 1) + width *= max_chars; + if (width < BITS_PER_CPPCHAR_T) { - 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); + mask = ((cppchar_t) 1 << width) - 1; + if (unsigned_p || !(result & (1 << (width - 1)))) + result &= mask; + else + result |= ~mask; } *pchars_seen = chars_seen; diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index 0e7d9e878a0..194175362a8 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -3512,19 +3512,21 @@ The preprocessor and compiler interpret character constants in the same way; i.e.@: escape sequences such as @samp{\a} are given the values they would have on the target machine. -Multi-character character constants are interpreted a character at a -time, shifting the previous result left by the number of bits per -target character and or-ing the value of the new character truncated -to the width of a target character. They have type @code{int}, and -are treated as signed regardless of whether single characters are -signed or not (a slight change from versions 3.1 and earlier of GCC). -If there are more characters in the constant than would fit in the -target @code{int} an error is issued. +The compiler values a multi-character character constant a character +at a time, shifting the previous value left by the number of bits per +target character, and then or-ing in the bit-pattern of the new +character truncated to the width of a target character. The final +bit-pattern is given type @code{int}, and is therefore signed, +regardless of whether single characters are signed or not (a slight +change from versions 3.1 and earlier of GCC). If there are more +characters in the constant than would fit in the target @code{int} the +compiler issues a warning, and the excess leading characters are +ignored. For example, 'ab' for a target with an 8-bit @code{char} would be interpreted as @w{(int) ((unsigned char) 'a' * 256 + (unsigned char) -'b')}, and 'a\234' as @w{(int) ((unsigned char) 'a' * 256 + (unsigned -char) '\234')}. +'b')}, and '\234a' as @w{(int) ((unsigned char) '\234' * 256 + (unsigned +char) 'a')}. @item Source file inclusion. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c1dc8493357..f0b7a1cf4d1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-05-08 Neil Booth <neil@daikokuya.demon.co.uk> + + * gcc.dg/cpp/charconst-4.c: More tests. + 2002-05-08 Mark Mitchell <mark@codesourcery.com> PR c/6569 diff --git a/gcc/testsuite/gcc.dg/cpp/charconst-4.c b/gcc/testsuite/gcc.dg/cpp/charconst-4.c new file mode 100644 index 00000000000..986ea80f57e --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/charconst-4.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. */ + +/* { dg-do run } */ +/* { dg-options "-Wno-multichar -fsigned-char" } */ + +/* This tests how overly-long multichar charconsts are truncated, and + whether "short" multichar charconsts are incorrectly sign extended + (regardless of char signedness). Preprocessor is used so that we + have only one place where the too long warning is generated, so + that the test works for all targets. + + Neil Booth, 8 May 2002. */ + +#include <limits.h> + +#if INT_MAX == 32767 +# define LONG_CHARCONST '!\234a' +# define SHORT_CHARCONST '\234a' +# define POS_CHARCONST '\1' +#elif INT_MAX == 2147483647 +# define LONG_CHARCONST '!\234abc' +# define SHORT_CHARCONST '\234abc' +# define POS_CHARCONST '\234a' +#elif INT_MAX == 9223372036854775807 +# define LONG_CHARCONST '!\234abcdefg' +# define SHORT_CHARCONST '\234abcdefg' +# define POS_CHARCONST '\234a' +#else +/* Target int size not handled, do something that won't fail. */ +# define LONG_CHARCONST '\234a' +# define SHORT_CHARCONST '\234a' +# define POS_CHARCONST '\1' +#endif + +#if POS_CHARCONST < 0 +# error Charconst incorrectly sign-extended +#endif + +#if LONG_CHARCONST != SHORT_CHARCONST /* { dg-warning "too long" "" } */ +# error Overly long charconst truncates wrongly for preprocessor +#endif + +int main () +{ + if (POS_CHARCONST < 0) + abort (); + if (LONG_CHARCONST != SHORT_CHARCONST) /* { dg-warning "too long" "" } */ + abort (); + return 0; +} |