This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: c/6300: [PATCH] sparcv9-sun-solaris2.7 gcc-3.1 C testsuite failure in gcc.dg/cpp/charconst.c


On Sun, Apr 21, 2002 at 06:11:36PM -0400, Kaveh R. Ghazi wrote:
> Yes, however now it appears on plain sparc- targets, not sparcv9-
> because of some config.guess hackery that was eventually reverted.
> (See the 4/18 comment I added to the PR description field.)

Thanks, I can reproduce it now.

The problem is that cpp_interpret_charconst will happily pass back a
value wider than the mode we actually want, as long as it fits in
HOST_WIDE_INT.  No one will notice on a completely 32-bit platform,
where sizeof(HOST_WIDE_INT) is equal to sizeof(target wchar_t) and
therefore no truncation is necessary.  And no one will notice on a
64-bit platform where wchar_t is equivalent to 'int', because in

int c = L'yadda...';

we'll think the constant is already the right width.  But
sparc-sun-solaris2.7 has HOST_WIDE_INT == long long and WCHAR_TYPE ==
long, which means we _do_ try to convert to int in the assignment and
we _do_ notice that the constant doesn't fit in 32 bits.

The cure is to call convert() to the proper type from lex_charconst,
instead of just smashing the type field.  I am bootstrapping the
appended change now.  If you could test it on solaris, I'd appreciate
it.

zw

	* c-lex.c (lex_charconst): Call convert to get constant in
	proper type; don't just smash the type field.

===================================================================
Index: c-lex.c
--- c-lex.c	20 Mar 2002 05:14:27 -0000	1.164.2.2
+++ c-lex.c	22 Apr 2002 01:22:29 -0000
@@ -1407,7 +1407,7 @@ lex_charconst (token)
      const cpp_token *token;
 {
   HOST_WIDE_INT result;
-  tree value;
+  tree type, value;
   unsigned int chars_seen;
  
   result = cpp_interpret_charconst (parse_in, token, warn_multichar,
@@ -1415,7 +1415,7 @@ lex_charconst (token)
   if (token->type == CPP_WCHAR)
     {
       value = build_int_2 (result, 0);
-      TREE_TYPE (value) = wchar_type_node;
+      type = wchar_type_node;
     }
   else
     {
@@ -1427,10 +1427,24 @@ lex_charconst (token)
       /* In C, a character constant has type 'int'.
  	 In C++ 'char', but multi-char charconsts have type 'int'.  */
       if (c_language == clk_cplusplus && chars_seen <= 1)
- 	TREE_TYPE (value) = char_type_node;
+	type = char_type_node;
       else
- 	TREE_TYPE (value) = integer_type_node;
+	type = integer_type_node;
     }
- 
+
+  /* cpp_interpret_charconst issues a warning if the constant
+     overflows, but if the number fits in HOST_WIDE_INT anyway, it
+     will return it un-truncated, which may cause problems down the
+     line.  So set the type to widest_integer_literal_type, call
+     convert to truncate it to the proper type, then clear
+     TREE_OVERFLOW so we don't get a second warning.
+
+     FIXME: cpplib's assessment of overflow may not be accurate on a
+     platform where the final type can change at (compiler's) runtime.  */
+
+  TREE_TYPE (value) = widest_integer_literal_type_node;
+  value = convert (type, value);
+  TREE_OVERFLOW (value) = 0;
+
   return value;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]