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]

[C++ PATCH]: Fix bug 2559 (long long template parms)


Hi,
I've installed this on both branch and mainline which fixes
the ICE about long long template parms. The code to emit int_csts
bigger than HOST_WIDE_INT was never written. Now it is.

built & tested on i686-pc-linux-gnu, approved by Mark.

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-04-26  Nathan Sidwell <nathan@codesourcery.com>

	* mangle.c (write_chars): New macro.
	(hwint_to_ascii): New function
	(write_number): Use it.
	(write_integer_cst): Deal with really big numbers.

Index: cp/mangle.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/mangle.c,v
retrieving revision 1.26.4.7
diff -c -3 -p -r1.26.4.7 mangle.c
*** mangle.c	2001/04/19 22:40:07	1.26.4.7
--- mangle.c	2001/04/26 08:27:31
*************** static void write_prefix PARAMS ((tree))
*** 153,158 ****
--- 153,159 ----
  static void write_template_prefix PARAMS ((tree));
  static void write_unqualified_name PARAMS ((tree));
  static void write_source_name PARAMS ((tree));
+ static int hwint_to_ascii PARAMS ((unsigned HOST_WIDE_INT, unsigned int, char *, unsigned));
  static void write_number PARAMS ((unsigned HOST_WIDE_INT, int,
  				  unsigned int));
  static void write_integer_cst PARAMS ((tree));
*************** static void write_java_integer_type_code
*** 198,203 ****
--- 199,208 ----
  #define write_char(CHAR)                                              \
    obstack_1grow (&G.name_obstack, (CHAR))
  
+ /* Append a sized buffer to the end of the mangled representation. */
+ #define write_chars(CHAR, LEN)                                        \
+   obstack_grow (&G.name_obstack, (CHAR), (LEN))
+ 
  /* Append a NUL-terminated string to the end of the mangled
     representation.  */
  #define write_string(STRING)                                          \
*************** write_source_name (identifier)
*** 1013,1018 ****
--- 1018,1055 ----
    write_identifier (IDENTIFIER_POINTER (identifier));
  }
  
+ /* Convert NUMBER to ascii using base BASE and generating at least
+    MIN_DIGITS characters. BUFFER points to the _end_ of the buffer
+    into which to store the characters. Returns the number of
+    characters generated (these will be layed out in advance of where
+    BUFFER points).  */
+ 
+ static int
+ hwint_to_ascii (number, base, buffer, min_digits)
+      unsigned HOST_WIDE_INT number;
+      unsigned int base;
+      char *buffer;
+      unsigned min_digits;
+ {
+   static const char base_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+   unsigned digits = 0;
+   
+   while (number)
+     {
+       unsigned HOST_WIDE_INT d = number / base;
+       
+       *--buffer = base_digits[number - d * base];
+       digits++;
+       number = d;
+     }
+   while (digits < min_digits)
+     {
+       *--buffer = base_digits[0];
+       digits++;
+     }
+   return digits;
+ }
+ 
  /* Non-terminal <number>.
  
       <number> ::= [n] </decimal integer/>  */
*************** write_number (number, unsigned_p, base)
*** 1023,1072 ****
       int unsigned_p;
       unsigned int base;
  {
!   static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
!   unsigned HOST_WIDE_INT n;
!   unsigned HOST_WIDE_INT m = 1;
  
    if (!unsigned_p && (HOST_WIDE_INT) number < 0)
      {
        write_char ('n');
        number = -((HOST_WIDE_INT) number);
-     }
-   
-   /* Figure out how many digits there are.  */
-   n = number;
-   while (n >= base)
-     {
-       n /= base;
-       m *= base;
-     }
- 
-   /* Write them out.  */
-   while (m > 0)
-     {
-       int digit = number / m;
-       write_char (digits[digit]);
-       number -= digit * m;
-       m /= base;
      }
! 
!   my_friendly_assert (number == 0, 20000407);
  }
  
! /* Write out an integeral CST in decimal.  */
  
  static inline void
  write_integer_cst (cst)
       tree cst;
  {
!   if (tree_int_cst_sgn (cst) >= 0) 
      {
!       if (TREE_INT_CST_HIGH (cst) != 0)
! 	sorry ("mangling very large integers");
!       write_unsigned_number (TREE_INT_CST_LOW (cst));
      }
!   else
!     write_signed_number (tree_low_cst (cst, 0));
  }
  
  /* Non-terminal <identifier>.
--- 1060,1150 ----
       int unsigned_p;
       unsigned int base;
  {
!   char buffer[sizeof (HOST_WIDE_INT) * 8];
!   unsigned count = 0;
  
    if (!unsigned_p && (HOST_WIDE_INT) number < 0)
      {
        write_char ('n');
        number = -((HOST_WIDE_INT) number);
      }
!   count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
!   write_chars (buffer + sizeof (buffer) - count, count);
  }
  
! /* Write out an integral CST in decimal. Most numbers are small, and
!    representable in a HOST_WIDE_INT. Occasionally we'll have numbers
!    bigger than that, which we must deal with. */
  
  static inline void
  write_integer_cst (cst)
       tree cst;
  {
!   int sign = tree_int_cst_sgn (cst);
! 
!   if (TREE_INT_CST_HIGH (cst) + (sign < 0))
      {
!       /* A bignum. We do this in chunks, each of which fits in a
! 	 HOST_WIDE_INT. */
!       char buffer[sizeof (HOST_WIDE_INT) * 8 * 2];
!       unsigned HOST_WIDE_INT chunk;
!       unsigned chunk_digits;
!       char *ptr = buffer + sizeof (buffer);
!       unsigned count = 0;
!       tree n, base, type;
!       int done;
! 
!       /* HOST_WIDE_INT must be at least 32 bits, so 10^9 is
! 	 representable. */
!       chunk = 1000000000;
!       chunk_digits = 9;
!       
!       if (sizeof (HOST_WIDE_INT) >= 8)
! 	{
! 	  /* It is at least 64 bits, so 10^18 is representable. */
! 	  chunk_digits = 18;
! 	  chunk *= chunk;
! 	}
!       
!       type = signed_or_unsigned_type (1, TREE_TYPE (cst));
!       base = build_int_2 (chunk, 0);
!       n = build_int_2 (TREE_INT_CST_LOW (cst), TREE_INT_CST_HIGH (cst));
!       TREE_TYPE (n) = TREE_TYPE (base) = type;
! 
!       if (sign < 0)
! 	{
! 	  write_char ('n');
! 	  n = fold (build1 (NEGATE_EXPR, type, n));
! 	}
!       do
! 	{
! 	  tree d = fold (build (FLOOR_DIV_EXPR, type, n, base));
! 	  tree tmp = fold (build (MULT_EXPR, type, d, base));
! 	  unsigned c;
! 	  
! 	  done = integer_zerop (d);
! 	  tmp = fold (build (MINUS_EXPR, type, n, tmp));
! 	  c = hwint_to_ascii (TREE_INT_CST_LOW (tmp), 10, ptr,
! 				done ? 1 : chunk_digits);
! 	  ptr -= c;
! 	  count += c;
! 	  n = d;
! 	}
!       while (!done);
!       write_chars (ptr, count);
      }
!   else 
!     {
!       /* A small num.  */
!       unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
!       
!       if (sign < 0)
! 	{
! 	  write_char ('n');
! 	  low = -low;
! 	}
!       write_unsigned_number (low);
!     }
  }
  
  /* Non-terminal <identifier>.
// Build don't link:
// 
// Copyright (C) 2001 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 25 April 2001 <nathan@codesourcery.com>
// Origin:pcarlini@unitus.it

// Bug 2559. We hadn't implemented code to mangle numbers bigger than
// HOST_WIDE_INT.

template<class T, T min_val, T max_val>
class integer_traits_base
{
public:
static const bool is_integral = true;
};

template<class T>
class integer_traits
{
public:
static const bool is_integral = false;
};

template<>
class integer_traits<long long>
: public integer_traits_base<long long, (-9223372036854775807LL - 1),
9223372036854775807LL>
{ };

integer_traits<long long> f;

template <class T, T value> T foo () 
{
  return value;
}

void x ()
{
  foo<long long, -9223372036854775807LL> ();
}

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