Commit a5a49440 by Neil Booth Committed by Neil Booth

c-common.c (warn_multichar): New.

	* 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.
cp:
	* Make-lang.in (decl2.o): Update.
	* cp-tree.h (warn_multichar): Remove.
	* decl2.c: Include c-common.h.
	(warn_multichar): Remove.
doc:
	* cpp.texi: Update documentation.
testsuite:
	* gcc.dg/cpp/charconst-3.c: Correct tests accordingly.

From-SVN: r53240
parent d7ee9f9f
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> 2002-05-06 Vladimir Makarov <vmakarov@redhat.com>
* genautomata.c (form_the_same_automaton_unit_lists_from_regexp): * genautomata.c (form_the_same_automaton_unit_lists_from_regexp):
......
...@@ -201,6 +201,10 @@ int flag_short_double; ...@@ -201,6 +201,10 @@ int flag_short_double;
int flag_short_wchar; 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. */ /* Nonzero means warn about possible violations of sequence point rules. */
int warn_sequence_point; int warn_sequence_point;
...@@ -4307,6 +4311,8 @@ c_common_init (filename) ...@@ -4307,6 +4311,8 @@ c_common_init (filename)
options->int_precision = TYPE_PRECISION (integer_type_node); options->int_precision = TYPE_PRECISION (integer_type_node);
options->wchar_precision = TYPE_PRECISION (wchar_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. */ /* NULL is passed up to toplev.c and we exit quickly. */
if (flag_preprocess_only) if (flag_preprocess_only)
{ {
......
...@@ -391,6 +391,9 @@ extern int flag_short_double; ...@@ -391,6 +391,9 @@ extern int flag_short_double;
extern int flag_short_wchar; 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. */ /* Warn about *printf or *scanf format/argument anomalies. */
extern int warn_format; extern int warn_format;
......
...@@ -426,10 +426,6 @@ int warn_sign_compare = -1; ...@@ -426,10 +426,6 @@ int warn_sign_compare = -1;
int warn_float_equal = 0; int warn_float_equal = 0;
/* Nonzero means warn about use of multicharacter literals. */
int warn_multichar = 1;
/* Nonzero means `$' can be in an identifier. */ /* Nonzero means `$' can be in an identifier. */
#ifndef DOLLARS_IN_IDENTIFIERS #ifndef DOLLARS_IN_IDENTIFIERS
......
...@@ -1359,7 +1359,7 @@ lex_charconst (token) ...@@ -1359,7 +1359,7 @@ lex_charconst (token)
unsigned int chars_seen; unsigned int chars_seen;
int unsignedp; int unsignedp;
result = cpp_interpret_charconst (parse_in, token, warn_multichar, result = cpp_interpret_charconst (parse_in, token,
&chars_seen, &unsignedp); &chars_seen, &unsignedp);
/* Cast to cppchar_signed_t to get correct sign-extension of RESULT /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
......
...@@ -374,10 +374,6 @@ extern int warn_sign_compare; ...@@ -374,10 +374,6 @@ extern int warn_sign_compare;
extern int warn_float_equal; 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. */ /* Nonzero means we are reading code that came from a system header file. */
extern int system_header_p; extern int system_header_p;
......
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> 2002-05-03 Jason Merrill <jason@redhat.com>
* tree.c (build_cplus_array_type): Only const and volatile get * tree.c (build_cplus_array_type): Only const and volatile get
......
...@@ -257,7 +257,7 @@ cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \ ...@@ -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) \ 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/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) \ 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) \ cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \
diagnostic.h diagnostic.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \ cp/typeck.o: cp/typeck.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
......
...@@ -3111,9 +3111,6 @@ extern int flag_ms_extensions; ...@@ -3111,9 +3111,6 @@ extern int flag_ms_extensions;
type signature of any virtual function in the base class. */ type signature of any virtual function in the base class. */
extern int warn_overloaded_virtual; 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 /* Set by add_implicitly_declared_members() to keep those members from
being flagged as deprecated or reported as using deprecated being flagged as deprecated or reported as using deprecated
types. */ types. */
......
...@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */
#include "timevar.h" #include "timevar.h"
#include "cpplib.h" #include "cpplib.h"
#include "target.h" #include "target.h"
#include "c-common.h"
extern cpp_reader *parse_in; extern cpp_reader *parse_in;
/* This structure contains information about the initializations /* This structure contains information about the initializations
...@@ -288,10 +289,6 @@ int warn_old_style_cast; ...@@ -288,10 +289,6 @@ int warn_old_style_cast;
int warn_unknown_pragmas; /* Tri state variable. */ 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 /* Nonzero means warn when non-templatized friend functions are
declared within a template */ declared within a template */
......
...@@ -295,7 +295,16 @@ eval_token (pfile, token) ...@@ -295,7 +295,16 @@ eval_token (pfile, token)
case CPP_WCHAR: case CPP_WCHAR:
case CPP_CHAR: 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; break;
case CPP_NAME: case CPP_NAME:
......
...@@ -487,6 +487,7 @@ cpp_create_reader (lang) ...@@ -487,6 +487,7 @@ cpp_create_reader (lang)
set_lang (pfile, lang); set_lang (pfile, lang);
CPP_OPTION (pfile, warn_import) = 1; CPP_OPTION (pfile, warn_import) = 1;
CPP_OPTION (pfile, warn_multichar) = 1;
CPP_OPTION (pfile, discard_comments) = 1; CPP_OPTION (pfile, discard_comments) = 1;
CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1; CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
CPP_OPTION (pfile, show_column) = 1; CPP_OPTION (pfile, show_column) = 1;
......
...@@ -1861,10 +1861,9 @@ cpp_parse_escape (pfile, pstr, limit, wide) ...@@ -1861,10 +1861,9 @@ cpp_parse_escape (pfile, pstr, limit, wide)
characters seen, and UNSIGNEDP to a variable that indicates whether characters seen, and UNSIGNEDP to a variable that indicates whether
the result has signed type. */ the result has signed type. */
cppchar_t cppchar_t
cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp) cpp_interpret_charconst (pfile, token, pchars_seen, unsignedp)
cpp_reader *pfile; cpp_reader *pfile;
const cpp_token *token; const cpp_token *token;
int warn_multi;
unsigned int *pchars_seen; unsigned int *pchars_seen;
int *unsignedp; int *unsignedp;
{ {
...@@ -1930,11 +1929,10 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp) ...@@ -1930,11 +1929,10 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp)
chars_seen++; chars_seen++;
/* Sign-extend the character, scale result, and add the two. */ /* Truncate the character, scale the result and merge the two. */
if (!unsigned_p && (c & (1 << (width - 1)))) c &= mask;
c |= ~mask;
if (width < BITS_PER_CPPCHAR_T) if (width < BITS_PER_CPPCHAR_T)
result = (result << width) + c; result = (result << width) | c;
else else
result = c; result = c;
} }
...@@ -1945,16 +1943,29 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp) ...@@ -1945,16 +1943,29 @@ cpp_interpret_charconst (pfile, token, warn_multi, pchars_seen, unsignedp)
{ {
/* Multichar charconsts are of type int and therefore signed. */ /* Multichar charconsts are of type int and therefore signed. */
unsigned_p = 0; unsigned_p = 0;
if (chars_seen > max_chars) if (chars_seen > max_chars)
{ {
chars_seen = max_chars; chars_seen = max_chars;
cpp_error (pfile, DL_WARNING, cpp_error (pfile, DL_WARNING,
"character constant too long for its type"); "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"); 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; *pchars_seen = chars_seen;
*unsignedp = unsigned_p; *unsignedp = unsigned_p;
return result; return result;
......
...@@ -196,10 +196,10 @@ struct cpp_token ...@@ -196,10 +196,10 @@ struct cpp_token
#ifndef MAX_WCHAR_TYPE_SIZE #ifndef MAX_WCHAR_TYPE_SIZE
# define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE # define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
#endif #endif
#if SIZEOF_INT >= MAX_WCHAR_TYPE_SIZE #if CHAR_BIT * SIZEOF_INT >= MAX_WCHAR_TYPE_SIZE
# define CPPCHAR_SIGNED_T int # define CPPCHAR_SIGNED_T int
#else #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 # define CPPCHAR_SIGNED_T long
# else # else
# define CPPCHAR_SIGNED_T long long # define CPPCHAR_SIGNED_T long long
...@@ -329,6 +329,9 @@ struct cpp_options ...@@ -329,6 +329,9 @@ struct cpp_options
/* Nonzero means warn if #import is used. */ /* Nonzero means warn if #import is used. */
unsigned char warn_import; unsigned char warn_import;
/* Nonzero means warn about multicharacter charconsts. */
unsigned char warn_multichar;
/* Nonzero means warn about various incompatibilities with /* Nonzero means warn about various incompatibilities with
traditional C. */ traditional C. */
unsigned char warn_traditional; unsigned char warn_traditional;
...@@ -558,7 +561,7 @@ extern void _cpp_backup_tokens PARAMS ((cpp_reader *, unsigned int)); ...@@ -558,7 +561,7 @@ extern void _cpp_backup_tokens PARAMS ((cpp_reader *, unsigned int));
/* Evaluate a CPP_CHAR or CPP_WCHAR token. */ /* Evaluate a CPP_CHAR or CPP_WCHAR token. */
extern cppchar_t extern cppchar_t
cpp_interpret_charconst PARAMS ((cpp_reader *, const cpp_token *, 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. /* Used to register builtins during the register_builtins callback.
The text is the same as the command line argument. */ The text is the same as the command line argument. */
......
...@@ -3514,19 +3514,17 @@ values they would have on the target machine. ...@@ -3514,19 +3514,17 @@ values they would have on the target machine.
Multi-character character constants are interpreted a character at a Multi-character character constants are interpreted a character at a
time, shifting the previous result left by the number of bits per time, shifting the previous result left by the number of bits per
target character and adding the sign-extended value of the new target character and or-ing the value of the new character truncated
character. They have type @code{int}, and are treated as signed to the width of a target character. They have type @code{int}, and
regardless of whether single characters are signed or not. If there are treated as signed regardless of whether single characters are
are more characters in the constant than would fit in the target signed or not (a slight change from versions 3.1 and earlier of GCC).
@code{int}, a diagnostic is given, and the excess leading characters If there are more characters in the constant than would fit in the
are ignored. This methodology is not fully compatible with versions target @code{int} an error is issued.
3.1 and earlier of GCC, which used a confusing and inconsistent
valuation technique.
For example, 'ab' for a target with an 8-bit @code{char} would be 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 + interpreted as @w{(int) ((unsigned char) 'a' * 256 + (unsigned char)
'\234'}. GCC 3.1 and earlier would give a different value for the 'b')}, and 'a\234' as @w{(int) ((unsigned char) 'a' * 256 + (unsigned
latter example, probably @w{'a' * 256 + (unsigned char) '\234'}. char) '\234')}.
@item Source file inclusion. @item Source file inclusion.
......
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> 2002-05-06 Neil Booth <neil@daikokuya.demon.co.uk>
* gcc.dg/cpp/charconst-3.c: Run, don't compile. * gcc.dg/cpp/charconst-3.c: Run, don't compile.
......
...@@ -15,23 +15,31 @@ int main () ...@@ -15,23 +15,31 @@ int main ()
#if INT_MAX > 127 #if INT_MAX > 127
int scale = (int) (unsigned char) -1 + 1; int scale = (int) (unsigned char) -1 + 1;
if ('ab' != ('a' * scale + 'b')) if ('ab' != (int) ((unsigned char) 'a' * scale + (unsigned char) 'b'))
abort (); abort ();
if ('\234b' != ('\234' * scale + 'b')) if ('\234b' != (int) ((unsigned char) '\234' * scale + (unsigned char) 'b'))
abort (); abort ();
if ('b\234' != ('b' * scale + '\234')) if ('b\234' != (int) ((unsigned char) 'b' * scale + (unsigned char) '\234'))
abort (); abort ();
/* Multichar charconsts have type int and should be signed. */ /* Multichar charconsts have type int and should be signed. */
#if INT_MAX == 32767 #if INT_MAX == 32767
# if '\234a' > 0
# error Preprocessor charconsts 1
# endif
if ('\234a' > 0) if ('\234a' > 0)
abort (); abort ();
#elif INT_MAX == 2147483647 #elif INT_MAX == 2147483647
# if '\234aaa' > 0
# error Preprocessor charconsts 2
# endif
if ('\234aaa' > 0) if ('\234aaa' > 0)
abort (); abort ();
#elif INT_MAX == 9223372036854775807 #elif INT_MAX == 9223372036854775807
# if '\234aaaaaaa' > 0
# error Preprocessor charconsts 3
# endif
if ('\234aaaaaaa' > 0) if ('\234aaaaaaa' > 0)
abort (); abort ();
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment