decl.c (reshape_init): Fix typo.
authorMark Mitchell <mark@codesourcery.com>
Tue, 15 Oct 2002 23:59:23 +0000 (23:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 15 Oct 2002 23:59:23 +0000 (23:59 +0000)
* decl.c (reshape_init): Fix typo.

* cp-tree.h (operator_name_info_t): Add arity.
* lex.c (init_operators): Initialize it.
* mangle.c (write_conversion_operator_name): New function.
(write_unqualified_name): Use it.
(write_template_args): Accept template arguments as a TREE_LIST.
(write_expression): Adjust handling of qualified names to match
specification.

* g++.dg/init/array6.C: New test.

* g++.dg/abi/mangle13.C: Likewise.
* g++.dg/abi/mangle14.C: Likewise.
* g++.dg/abi/mangle15.C: Likewise.

From-SVN: r58185

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/lex.c
gcc/cp/mangle.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/array6.C [new file with mode: 0644]

index 211f275..c529abb 100644 (file)
@@ -1,3 +1,15 @@
+2002-10-15  Mark Mitchell  <mark@codesourcery.com>
+
+       * decl.c (reshape_init): Fix typo.
+
+       * cp-tree.h (operator_name_info_t): Add arity.
+       * lex.c (init_operators): Initialize it.
+       * mangle.c (write_conversion_operator_name): New function.
+       (write_unqualified_name): Use it.
+       (write_template_args): Accept template arguments as a TREE_LIST.
+       (write_expression): Adjust handling of qualified names to match
+       specification.
+
 2002-10-15  Jason Merrill  <jason@redhat.com>
 
        * call.c (call_builtin_trap): New fn.
index c834440..52f921c 100644 (file)
@@ -3481,6 +3481,8 @@ typedef struct operator_name_info_t
   const char *name;
   /* The mangled name of the operator.  */
   const char *mangled_name;
+  /* The arity of the operator.  */
+  int arity;
 } operator_name_info_t;
 
 /* A mapping from tree codes to operator name information.  */
index d122dfb..70d5d31 100644 (file)
@@ -7836,7 +7836,7 @@ reshape_init (tree type, tree *initp)
       return old_init;
     }
 
-  if (TREE_CODE (old_init) == STRING_CST
+  if (TREE_CODE (old_init_value) == STRING_CST
       && TREE_CODE (type) == ARRAY_TYPE
       && char_type_p (TREE_TYPE (type)))
     {
index bab2988..4558940 100644 (file)
@@ -263,7 +263,8 @@ init_operators ()
         : &operator_name_info[(int) CODE]);                                \
   oni->identifier = identifier;                                                    \
   oni->name = NAME;                                                        \
-  oni->mangled_name = MANGLING;
+  oni->mangled_name = MANGLING;                                             \
+  oni->arity = ARITY;
 
 #include "operators.def"
 #undef DEF_OPERATOR
index 76fd5f7..642bc73 100644 (file)
@@ -166,6 +166,7 @@ static void write_nested_name PARAMS ((tree));
 static void write_prefix PARAMS ((tree));
 static void write_template_prefix PARAMS ((tree));
 static void write_unqualified_name PARAMS ((tree));
+static void write_conversion_operator_name (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,
@@ -1016,8 +1017,7 @@ write_unqualified_name (decl)
        }
       else
        type = TREE_TYPE (DECL_NAME (decl));
-      write_string ("cv");
-      write_type (type);
+      write_conversion_operator_name (type);
     }
   else if (DECL_OVERLOADED_OPERATOR_P (decl))
     {
@@ -1033,6 +1033,15 @@ write_unqualified_name (decl)
     write_source_name (DECL_NAME (decl));
 }
 
+/* Write the unqualified-name for a conversion operator to TYPE.  */
+
+static void
+write_conversion_operator_name (tree type)
+{
+  write_string ("cv");
+  write_type (type);
+}
+
 /* Non-termial <source-name>.  IDENTIFIER is an IDENTIFIER_NODE.  
 
      <source-name> ::= </length/ number> <identifier>  */
@@ -1780,24 +1789,37 @@ static void
 write_template_args (args)
      tree args;
 {
-  int i;
-  int length = TREE_VEC_LENGTH (args);
-
   MANGLE_TRACE_TREE ("template-args", args);
 
-  my_friendly_assert (length > 0, 20000422);
+  write_char ('I');
 
-  if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+  if (TREE_CODE (args) == TREE_VEC)
     {
-      /* We have nested template args.  We want the innermost template
-        argument list.  */
-      args = TREE_VEC_ELT (args, length - 1);
-      length = TREE_VEC_LENGTH (args);
+      int i;
+      int length = TREE_VEC_LENGTH (args);
+      my_friendly_assert (length > 0, 20000422);
+
+      if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+       {
+         /* We have nested template args.  We want the innermost template
+            argument list.  */
+         args = TREE_VEC_ELT (args, length - 1);
+         length = TREE_VEC_LENGTH (args);
+       }
+      for (i = 0; i < length; ++i)
+       write_template_arg (TREE_VEC_ELT (args, i));
+    }
+  else 
+    {
+      my_friendly_assert (TREE_CODE (args) == TREE_LIST, 20021014);
+
+      while (args)
+       {
+         write_template_arg (TREE_VALUE (args));
+         args = TREE_CHAIN (args);
+       }
     }
 
-  write_char ('I');
-  for (i = 0; i < length; ++i)
-    write_template_arg (TREE_VEC_ELT (args, i));
   write_char ('E');
 }
 
@@ -1807,7 +1829,9 @@ write_template_args (args)
 
    <expr-primary> ::= <template-param>
                  ::= L <type> <value number> E  # literal
-                 ::= L <mangled-name> E         # external name  */
+                 ::= L <mangled-name> E         # external name  
+                  ::= sr <type> <unqualified-name>
+                  ::= sr <type> <unqualified-name> <template-args> */
 
 static void
 write_expression (expr)
@@ -1859,6 +1883,75 @@ write_expression (expr)
       write_string ("st");
       write_type (TREE_OPERAND (expr, 0));
     }
+  else if (abi_version_at_least (2) && TREE_CODE (expr) == SCOPE_REF)
+    {
+      tree scope = TREE_OPERAND (expr, 0);
+      tree member = TREE_OPERAND (expr, 1);
+
+      /* If the MEMBER is a real declaration, then the qualifying
+        scope was not dependent.  Ideally, we would not have a
+        SCOPE_REF in those cases, but sometimes we do.  If the second
+        argument is a DECL, then the name must not have been
+        dependent.  */
+      if (DECL_P (member))
+       write_expression (member);
+      else
+       {
+         tree template_args;
+
+         write_string ("sr");
+         write_type (scope);
+         /* If MEMBER is a template-id, separate the template
+            from the arguments.  */
+         if (TREE_CODE (member) == TEMPLATE_ID_EXPR)
+           {
+             template_args = TREE_OPERAND (member, 1);
+             member = TREE_OPERAND (member, 0);
+             if (TREE_CODE (member) == LOOKUP_EXPR)
+               member = TREE_OPERAND (member, 0);
+           }
+         else
+           template_args = NULL_TREE;
+         /* Write out the name of the MEMBER.  */
+         if (IDENTIFIER_TYPENAME_P (member))
+           write_conversion_operator_name (TREE_TYPE (member));
+         else if (IDENTIFIER_OPNAME_P (member))
+           {
+             int i;
+             const char *mangled_name = NULL;
+
+             /* Unfortunately, there is no easy way to go from the
+                name of the operator back to the corresponding tree
+                code.  */
+             for (i = 0; i < LAST_CPLUS_TREE_CODE; ++i)
+               if (operator_name_info[i].identifier == member)
+                 {
+                   /* The ABI says that we prefer binary operator
+                      names to unary operator names.  */
+                   if (operator_name_info[i].arity == 2)
+                     {
+                       mangled_name = operator_name_info[i].mangled_name;
+                       break;
+                     }
+                   else if (!mangled_name)
+                     mangled_name = operator_name_info[i].mangled_name;
+                 }
+               else if (assignment_operator_name_info[i].identifier
+                        == member)
+                 {
+                   mangled_name 
+                     = assignment_operator_name_info[i].mangled_name;
+                   break;
+                 }
+             write_string (mangled_name);
+           }
+         else
+           write_source_name (member);
+         /* Write out the template arguments.  */
+         if (template_args)
+           write_template_args (template_args);
+       }
+    }
   else
     {
       int i;
@@ -1880,7 +1973,7 @@ write_expression (expr)
 
          code = TREE_CODE (expr);
        }
-      
+
       /* If it wasn't any of those, recursively expand the expression.  */
       write_string (operator_name_info[(int) code].mangled_name);
 
@@ -1904,7 +1997,12 @@ write_expression (expr)
          if (TREE_CODE (TREE_OPERAND (expr, 1)) == IDENTIFIER_NODE)
            write_source_name (TREE_OPERAND (expr, 1));
          else
-           write_encoding (TREE_OPERAND (expr, 1));
+           {
+             /* G++ 3.2 incorrectly put out both the "sr" code and
+                the nested name of the qualified name.  */
+             G.need_abi_warning = 1;
+             write_encoding (TREE_OPERAND (expr, 1));
+           }
          break;
 
        default:
index 20de763..50f478f 100644 (file)
@@ -1,7 +1,15 @@
+2002-10-15  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/init/array6.C: New test.
+       
+       * g++.dg/abi/mangle13.C: Likewise.
+       * g++.dg/abi/mangle14.C: Likewise.
+       * g++.dg/abi/mangle15.C: Likewise.
+
 2002-10-14  Mark Mitchell  <mark@codesourcery.com>
 
        * g++.dg/abi/empty8.C: New test.
-
+       
 2002-10-15  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.dg/init/ctor1.C: New test.
diff --git a/gcc/testsuite/g++.dg/abi/mangle13.C b/gcc/testsuite/g++.dg/abi/mangle13.C
new file mode 100644 (file)
index 0000000..716c4c3
--- /dev/null
@@ -0,0 +1,28 @@
+// { dg-options "-fabi-version=0" }
+
+struct A {
+  template <typename T> int f ();
+  int operator+();
+  operator int ();
+  template <typename T> 
+  int operator-();
+};
+
+typedef int (A::*P)();
+
+template <P> struct S {};
+
+template <typename T> void g (S<&T::template f<int> >) {}
+template <typename T> void g (S<&T::operator+ >) {}
+template <typename T> void g (S<&T::operator int>) {}
+template <typename T> void g (S<&T::template operator- <double> >) {}
+
+template void g<A> (S<&A::f<int> >);
+template void g<A> (S<&A::operator+>);
+template void g<A> (S<&A::operator int>);
+template void g<A> (S<&A::operator-<double> >);
+
+// { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_1fIiEEE } }
+// { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_plEE } }
+// { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_cviEE } }
+// { dg-final { scan-assembler _Z1gI1AEv1SIXadsrT_miIdEEE } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle14.C b/gcc/testsuite/g++.dg/abi/mangle14.C
new file mode 100644 (file)
index 0000000..8e2bfdd
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-do compile }
+// { dg-options "-Wabi" }
+
+struct A {
+  template <typename T> int f ();
+};
+
+typedef int (A::*P)();
+
+template <P> struct S {};
+
+void g (S<&A::f<int> >) {} // { dg-warning "mangle" }
diff --git a/gcc/testsuite/g++.dg/abi/mangle15.C b/gcc/testsuite/g++.dg/abi/mangle15.C
new file mode 100644 (file)
index 0000000..3c112e2
--- /dev/null
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-fabi-version=0" }
+
+struct A {
+  template <typename T> int f ();
+};
+
+typedef int (A::*P)();
+
+template <P> struct S {};
+
+void g (S<&A::f<int> >) {}
+
+// { dg-final { scan-assembler _Z1g1SIXadL_ZN1A1fIiEEivEEE } }
diff --git a/gcc/testsuite/g++.dg/init/array6.C b/gcc/testsuite/g++.dg/init/array6.C
new file mode 100644 (file)
index 0000000..1b04709
--- /dev/null
@@ -0,0 +1,3 @@
+// { dg-do compile }
+
+char arr [][4] = { "one", "two" };