aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/c-common.c6
-rw-r--r--gcc/c-common.h3
-rw-r--r--gcc/c-decl.c4
-rw-r--r--gcc/c-lex.c2
-rw-r--r--gcc/c-tree.h4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/Make-lang.in2
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/cppexp.c11
-rw-r--r--gcc/cppinit.c1
-rw-r--r--gcc/cpplex.c25
-rw-r--r--gcc/cpplib.h9
-rw-r--r--gcc/doc/cpp.texi20
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/charconst-3.c16
17 files changed, 97 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 00084d7..d88c973 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * c-common.c (warn_multichar): New.
+ (c_common_init): Set CPP's warn_multichar.
+ * c-common.h (warn_multichar): New.
+ * c-decl.c (warn_multichar): Remove.
+ * c-lex.c (lex_charconst): Update.
+ * c-tree.h (warn_multichar): Remove.
+ * cppexp.c (eval_token): Sign-extend charconst value.
+ * cppinit.c (cpp_create_reader): Set warn_multichar.
+ * cpplex.c (cpp_interpret_charconst): Don't sign-extend
+ each character. Update prototype. Sign-extend the result.
+ * cpplib.h: Fix conditions.
+ (struct cpp_options): Add new warning flag.
+ (cpp_interpret_charconst): Update prototype.
+doc:
+ * cpp.texi: Update documentation.
+
2002-05-06 Vladimir Makarov <vmakarov@redhat.com>
* genautomata.c (form_the_same_automaton_unit_lists_from_regexp):
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 72c4988b..bc4b0b9 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -201,6 +201,10 @@ int flag_short_double;
int flag_short_wchar;
+/* Nonzero means warn about use of multicharacter literals. */
+
+int warn_multichar = 1;
+
/* Nonzero means warn about possible violations of sequence point rules. */
int warn_sequence_point;
@@ -4307,6 +4311,8 @@ c_common_init (filename)
options->int_precision = TYPE_PRECISION (integer_type_node);
options->wchar_precision = TYPE_PRECISION (wchar_type_node);
+ options->warn_multichar = warn_multichar;
+
/* NULL is passed up to toplev.c and we exit quickly. */
if (flag_preprocess_only)
{
diff --git a/gcc/c-common.h b/gcc/c-common.h
index a8439d4..eca6cf1 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -391,6 +391,9 @@ extern int flag_short_double;
extern int flag_short_wchar;
+/* Nonzero means warn about use of multicharacter literals. */
+extern int warn_multichar;
+
/* Warn about *printf or *scanf format/argument anomalies. */
extern int warn_format;
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index ae4cebb..61f8f69 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -426,10 +426,6 @@ int warn_sign_compare = -1;
int warn_float_equal = 0;
-/* Nonzero means warn about use of multicharacter literals. */
-
-int warn_multichar = 1;
-
/* Nonzero means `$' can be in an identifier. */
#ifndef DOLLARS_IN_IDENTIFIERS
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 9679b60..075a2ed 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -1359,7 +1359,7 @@ lex_charconst (token)
unsigned int chars_seen;
int unsignedp;
- result = cpp_interpret_charconst (parse_in, token, warn_multichar,
+ result = cpp_interpret_charconst (parse_in, token,
&chars_seen, &unsignedp);
/* Cast to cppchar_signed_t to get correct sign-extension of RESULT
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 7225f5d..8ed0b64 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -374,10 +374,6 @@ extern int warn_sign_compare;
extern int warn_float_equal;
-/* Warn about multicharacter constants. */
-
-extern int warn_multichar;
-
/* Nonzero means we are reading code that came from a system header file. */
extern int system_header_p;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 29ced82..6cd79d7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * Make-lang.in (decl2.o): Update.
+ * cp-tree.h (warn_multichar): Remove.
+ * decl2.c: Include c-common.h.
+ (warn_multichar): Remove.
+
2002-05-03 Jason Merrill <jason@redhat.com>
* tree.c (build_cplus_array_type): Only const and volatile get
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 6db4e4c..06052f4 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -257,7 +257,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \
output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \
cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
- output.h except.h toplev.h $(GGC_H) $(RTL_H)
+ output.h except.h toplev.h $(GGC_H) $(RTL_H) c-common.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8be1e6f..db74366 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3111,9 +3111,6 @@ extern int flag_ms_extensions;
type signature of any virtual function in the base class. */
extern int warn_overloaded_virtual;
-/* Nonzero means warn about use of multicharacter literals. */
-extern int warn_multichar;
-
/* Set by add_implicitly_declared_members() to keep those members from
being flagged as deprecated or reported as using deprecated
types. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a904c0d..f716de0 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
+#include "c-common.h"
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
@@ -288,10 +289,6 @@ int warn_old_style_cast;
int warn_unknown_pragmas; /* Tri state variable. */
-/* Nonzero means warn about use of multicharacter literals. */
-
-int warn_multichar = 1;
-
/* Nonzero means warn when non-templatized friend functions are
declared within a template */
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index b71b02a..288cdd4 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -295,7 +295,16 @@ eval_token (pfile, token)
case CPP_WCHAR:
case CPP_CHAR:
- op.value = cpp_interpret_charconst (pfile, token, 1, &temp, &unsignedp);
+ {
+ cppchar_t result = cpp_interpret_charconst (pfile, token,
+ &temp, &unsignedp);
+ op.value = result;
+ /* Sign-extend the result if necessary. */
+ if (!unsignedp && (cppchar_signed_t) result < 0
+ && sizeof (HOST_WIDEST_INT) > sizeof (cppchar_t))
+ op.value |= ~(((unsigned HOST_WIDEST_INT) 1 << BITS_PER_CPPCHAR_T)
+ - 1);
+ }
break;
case CPP_NAME:
diff --git a/gcc/cppinit.c b/gcc/cppinit.c
index 974a1eb..1d570b0 100644
--- a/gcc/cppinit.c
+++ b/gcc/cppinit.c
@@ -487,6 +487,7 @@ cpp_create_reader (lang)
set_lang (pfile, lang);
CPP_OPTION (pfile, warn_import) = 1;
+ CPP_OPTION (pfile, warn_multichar) = 1;
CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
CPP_OPTION (pfile, show_column) = 1;
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;
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index 42eae91..ca0eee2 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -196,10 +196,10 @@ struct cpp_token
#ifndef MAX_WCHAR_TYPE_SIZE
# define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif
-#if SIZEOF_INT >= MAX_WCHAR_TYPE_SIZE
+#if CHAR_BIT * SIZEOF_INT >= MAX_WCHAR_TYPE_SIZE
# define CPPCHAR_SIGNED_T int
#else
-# if SIZEOF_LONG >= MAX_WCHAR_TYPE_SIZE || !HAVE_LONG_LONG
+# if CHAR_BIT * SIZEOF_LONG >= MAX_WCHAR_TYPE_SIZE || !HAVE_LONG_LONG
# define CPPCHAR_SIGNED_T long
# else
# define CPPCHAR_SIGNED_T long long
@@ -329,6 +329,9 @@ struct cpp_options
/* Nonzero means warn if #import is used. */
unsigned char warn_import;
+ /* Nonzero means warn about multicharacter charconsts. */
+ unsigned char warn_multichar;
+
/* Nonzero means warn about various incompatibilities with
traditional C. */
unsigned char warn_traditional;
@@ -558,7 +561,7 @@ extern void _cpp_backup_tokens PARAMS ((cpp_reader *, unsigned int));
/* Evaluate a CPP_CHAR or CPP_WCHAR token. */
extern cppchar_t
cpp_interpret_charconst PARAMS ((cpp_reader *, const cpp_token *,
- int, unsigned int *, int *));
+ unsigned int *, int *));
/* Used to register builtins during the register_builtins callback.
The text is the same as the command line argument. */
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 7ba498d..0e7d9e8 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -3514,19 +3514,17 @@ 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 adding the sign-extended value of the new
-character. They have type @code{int}, and are treated as signed
-regardless of whether single characters are signed or not. If there
-are more characters in the constant than would fit in the target
-@code{int}, a diagnostic is given, and the excess leading characters
-are ignored. This methodology is not fully compatible with versions
-3.1 and earlier of GCC, which used a confusing and inconsistent
-valuation technique.
+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.
For example, 'ab' for a target with an 8-bit @code{char} would be
-interpreted as @w{'a' * 256 + 'b'}, and 'a\234' as @w{'a' * 256 +
-'\234'}. GCC 3.1 and earlier would give a different value for the
-latter example, probably @w{'a' * 256 + (unsigned char) '\234'}.
+interpreted as @w{(int) ((unsigned char) 'a' * 256 + (unsigned char)
+'b')}, and 'a\234' as @w{(int) ((unsigned char) 'a' * 256 + (unsigned
+char) '\234')}.
@item Source file inclusion.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ab68f45..1b8bd71 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2002-05-07 Neil Booth <neil@daikokuya.demon.co.uk>
+
+ * gcc.dg/cpp/charconst-3.c: Correct tests accordingly.
+
2002-05-06 Neil Booth <neil@daikokuya.demon.co.uk>
* gcc.dg/cpp/charconst-3.c: Run, don't compile.
diff --git a/gcc/testsuite/gcc.dg/cpp/charconst-3.c b/gcc/testsuite/gcc.dg/cpp/charconst-3.c
index 2b62400..9d7d239 100644
--- a/gcc/testsuite/gcc.dg/cpp/charconst-3.c
+++ b/gcc/testsuite/gcc.dg/cpp/charconst-3.c
@@ -15,23 +15,31 @@ int main ()
#if INT_MAX > 127
int scale = (int) (unsigned char) -1 + 1;
- if ('ab' != ('a' * scale + 'b'))
+ if ('ab' != (int) ((unsigned char) 'a' * scale + (unsigned char) 'b'))
abort ();
- if ('\234b' != ('\234' * scale + 'b'))
+ if ('\234b' != (int) ((unsigned char) '\234' * scale + (unsigned char) 'b'))
abort ();
- if ('b\234' != ('b' * scale + '\234'))
+ if ('b\234' != (int) ((unsigned char) 'b' * scale + (unsigned char) '\234'))
abort ();
-
/* Multichar charconsts have type int and should be signed. */
#if INT_MAX == 32767
+# if '\234a' > 0
+# error Preprocessor charconsts 1
+# endif
if ('\234a' > 0)
abort ();
#elif INT_MAX == 2147483647
+# if '\234aaa' > 0
+# error Preprocessor charconsts 2
+# endif
if ('\234aaa' > 0)
abort ();
#elif INT_MAX == 9223372036854775807
+# if '\234aaaaaaa' > 0
+# error Preprocessor charconsts 3
+# endif
if ('\234aaaaaaa' > 0)
abort ();
#endif