OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Apr 2001 08:34:06 +0000 (08:34 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 26 Apr 2001 08:34:06 +0000 (08:34 +0000)
* mangle.c (write_chars): New macro.
(hwint_to_ascii): New function
(write_number): Use it.
(write_integer_cst): Deal with really big numbers.
testsuite:
* g++.old-deja/g++.pt/mangle2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41584 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/mangle.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.pt/mangle2.C [new file with mode: 0644]

index 40d6d96..d6c2f48 100644 (file)
@@ -1,3 +1,10 @@
+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.
+
 2001-04-25  Mark Mitchell  <mark@codesourcery.com>
 
        * optimize.c (maybe_clone_body): Copy TREE_PUBLIC before emitting
index 7b6857d..e193f00 100644 (file)
@@ -153,6 +153,7 @@ static void write_prefix PARAMS ((tree));
 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));
@@ -198,6 +199,10 @@ static void write_java_integer_type_codes PARAMS ((tree));
 #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)                                          \
@@ -1013,6 +1018,38 @@ write_source_name (identifier)
   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/>  */
@@ -1023,50 +1060,91 @@ write_number (number, unsigned_p, base)
      int unsigned_p;
      unsigned int base;
 {
-  static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  unsigned HOST_WIDE_INT n;
-  unsigned HOST_WIDE_INT m = 1;
+  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);
     }
-  
-  /* 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);
+  count = hwint_to_ascii (number, base, buffer + sizeof (buffer), 1);
+  write_chars (buffer + sizeof (buffer) - count, count);
 }
 
-/* Write out an integeral CST in decimal.  */
+/* 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;
 {
-  if (tree_int_cst_sgn (cst) >= 0) 
+  int sign = tree_int_cst_sgn (cst);
+
+  if (TREE_INT_CST_HIGH (cst) + (sign < 0))
     {
-      if (TREE_INT_CST_HIGH (cst) != 0)
-       sorry ("mangling very large integers");
-      write_unsigned_number (TREE_INT_CST_LOW (cst));
+      /* 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);
     }
-  else
-    write_signed_number (tree_low_cst (cst, 0));
 }
 
 /* Non-terminal <identifier>.
index 14f70fd..8025228 100644 (file)
@@ -1,3 +1,7 @@
+2001-04-26  Nathan Sidwell <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.pt/mangle2.C: New test.
+
 2001-04-25  Jakub Jelinek  <jakub@redhat.com>
 
        * c-format.c (check_format_info_recurse): Handle
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/mangle2.C b/gcc/testsuite/g++.old-deja/g++.pt/mangle2.C
new file mode 100644 (file)
index 0000000..a7b95b1
--- /dev/null
@@ -0,0 +1,40 @@
+// 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> ();
+}