This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
cpplib: Final charconst patch
- From: Neil Booth <neil at daikokuya dot demon dot co dot uk>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 8 May 2002 22:00:07 +0100
- Subject: cpplib: Final charconst patch
Too-long charconsts issue a warning, but I'd misread it as
an error because all diagnostics now go through cpp_error()
8-). So I wasn't bothering to truncate the answer.
Fixed thus, along with clarification of docs and more
testcases. Nothing should be able to change about charconst
valuation now without triggering a testcase failure somewhere.
Neil.
* 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.
Index: cpplex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplex.c,v
retrieving revision 1.204
diff -u -p -r1.204 cpplex.c
--- cpplex.c 7 May 2002 21:07:14 -0000 1.204
+++ cpplex.c 8 May 2002 20:53:43 -0000
@@ -1954,16 +1954,18 @@ cpp_interpret_charconst (pfile, token, p
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;
Index: doc/cpp.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/cpp.texi,v
retrieving revision 1.33
diff -u -p -r1.33 cpp.texi
--- doc/cpp.texi 6 May 2002 22:53:09 -0000 1.33
+++ doc/cpp.texi 8 May 2002 20:53:59 -0000
@@ -3512,19 +3512,21 @@ The preprocessor and compiler interpret
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.
Index: testsuite/gcc.dg/cpp/charconst-4.c
===================================================================
RCS file: testsuite/gcc.dg/cpp/charconst-4.c
diff -N testsuite/gcc.dg/cpp/charconst-4.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cpp/charconst-4.c 8 May 2002 20:53:59 -0000
@@ -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;
+}