re PR c++/8006 (ice in mangle_conv_op_name_for_type boost regression)
authorMark Mitchell <mark@codesourcery.com>
Fri, 4 Oct 2002 04:59:39 +0000 (04:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 4 Oct 2002 04:59:39 +0000 (04:59 +0000)
* doc/invoke.texi (-Wabi): Document mangling bug.

PR c++/8006
* mangle.c (CLASSTYPE_TEMPLATE_ID_P): Handle instances of template
template parameters.
(globals): Add entity and need_abi_warning.
(decl_is_template_id): Use TYPE_TEMPLATE_INFO, not
CLASSTYPE_TEMPLATE_INFO.
(is_std_substitution): Use CLASSTYPE_TI_TEMPLATE, not
TYPE_TI_TEMPLATE.
(write_prefix): Handle typename types correctly.
(write_template_prefix): Handle template template parameters
correctly.
(start_mangling): Add entity parameter.
(finish_mangling): Warn about names whose mangling will change.
(mangle_decl_string): Adjust.
(mangle_type_string): Likewise.
(mangle_special_for_type): Likewise.
(mangle_ctor_vtbl_for_type): Likewise.
(mangle_thunk): Likewise.
(mangle_guard_variable): Likewise.
(mangle_ref_init_variable): Likewise.

PR c++/8006
* g++.dg/abi/mangle9.C: New test.
* g++.dg/abi/mangle10.C: New test.
* g++.dg/abi/mangle11.C: New test.
* g++.dg/abi/mangle12.C: New test.

From-SVN: r57799

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/mangle.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/abi/mangle9.C [new file with mode: 0644]

index ffd1b531762aebc0ea9424c9ac806f3860151937..a664139beb4909c9875d7be6504de24c5f7b1f6f 100644 (file)
@@ -1,3 +1,7 @@
+2002-10-03  Mark Mitchell  <mark@codesourcery.com>
+
+       * doc/invoke.texi (-Wabi): Document mangling bug.
+
 2002-10-04  Alan Modra  <amodra@bigpond.net.au>
 
        * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Use a
index 521b4971ce1b0302809c25ed2b62b4c5840fb683..f10a56466b923a39472b00eb0add9b0c867dec63 100644 (file)
@@ -1,3 +1,26 @@
+2002-10-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/8006
+       * mangle.c (CLASSTYPE_TEMPLATE_ID_P): Handle instances of template
+       template parameters.
+       (globals): Add entity and need_abi_warning.
+       (decl_is_template_id): Use TYPE_TEMPLATE_INFO, not
+       CLASSTYPE_TEMPLATE_INFO.
+       (is_std_substitution): Use CLASSTYPE_TI_TEMPLATE, not
+       TYPE_TI_TEMPLATE.
+       (write_prefix): Handle typename types correctly.
+       (write_template_prefix): Handle template template parameters
+       correctly.
+       (start_mangling): Add entity parameter.
+       (finish_mangling): Warn about names whose mangling will change.
+       (mangle_decl_string): Adjust.
+       (mangle_type_string): Likewise.
+       (mangle_special_for_type): Likewise.
+       (mangle_ctor_vtbl_for_type): Likewise.
+       (mangle_thunk): Likewise.
+       (mangle_guard_variable): Likewise.
+       (mangle_ref_init_variable): Likewise.
+
 2002-10-02  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/7188.
index c7bd31299dbca0b5f29577498136f2870bd327df..76fd5f7e425695c2b66359b9fd907e2e139e0085 100644 (file)
    that hard to distinguish A<T> from A, where A<T> is the type as
    instantiated outside of the template, and A is the type used
    without parameters inside the template.  */
-#define CLASSTYPE_TEMPLATE_ID_P(NODE)                                \
-  (TYPE_LANG_SPECIFIC (NODE) != NULL                                 \
-   && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                          \
-   && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))
+#define CLASSTYPE_TEMPLATE_ID_P(NODE)                                  \
+  (TYPE_LANG_SPECIFIC (NODE) != NULL                                   \
+   && (TREE_CODE (NODE) == BOUND_TEMPLATE_TEMPLATE_PARM                        \
+       || (CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                      \
+          && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))))))
 
 /* Things we only need one of.  This module is not reentrant.  */
 static struct globals
@@ -95,10 +96,17 @@ static struct globals
      we've seen them.  */
   varray_type substitutions;
 
+  /* The entity that is being mangled.  */
+  tree entity;
+
   /* We are mangling an internal symbol. It is important to keep those
      involving template parmeters distinct by distinguishing their level
      and, for non-type parms, their type.  */
   bool internal_mangling_p;
+
+  /* True if the mangling will be different in a future version of the
+     ABI.  */
+  bool need_abi_warning;
 } G;
 
 /* Indices into subst_identifiers.  These are identifiers used in
@@ -192,8 +200,8 @@ static const char *mangle_decl_string PARAMS ((tree));
 
 /* Control functions.  */
 
-static inline void start_mangling PARAMS ((void));
-static inline const char *finish_mangling PARAMS ((void));
+static inline void start_mangling (tree);
+static inline const char *finish_mangling (bool);
 static tree mangle_special_for_type PARAMS ((tree, const char *));
 
 /* Foreign language functions.  */
@@ -250,7 +258,7 @@ decl_is_template_id (decl, template_info)
          if (template_info != NULL)
            /* For a templated TYPE_DECL, the template info is hanging
               off the type.  */
-           *template_info = CLASSTYPE_TEMPLATE_INFO (type);
+           *template_info = TYPE_TEMPLATE_INFO (type);
          return 1;
        }
     } 
@@ -398,8 +406,8 @@ is_std_substitution (node, index)
 
   return (DECL_NAMESPACE_STD_P (CP_DECL_CONTEXT (decl))
          && TYPE_LANG_SPECIFIC (type) 
-         && CLASSTYPE_TEMPLATE_INFO (type)
-         && (DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)) 
+         && TYPE_TEMPLATE_INFO (type)
+         && (DECL_NAME (TYPE_TI_TEMPLATE (type)) 
              == subst_identifiers[index]));
 }
 
@@ -837,7 +845,8 @@ write_nested_name (decl)
   write_char ('E');
 }
 
-/* <prefix> ::= <prefix> <unqualified-name>>
+/* <prefix> ::= <prefix> <unqualified-name>
+            ::= <template-param>
             ::= <template-prefix> <template-args>
            ::= # empty
            ::= <substitution>  */
@@ -860,7 +869,6 @@ write_prefix (node)
     return;
 
   if (DECL_P (node))
-    /* Node is a decl.  */
     {
       /* If this is a function decl, that means we've hit function
         scope, so this prefix must be for a local name.  In this
@@ -874,14 +882,22 @@ write_prefix (node)
       decl_is_template_id (decl, &template_info);
     }
   else
-    /* Node is a type.  */
     {
+      /* Node is a type.  */
       decl = TYPE_NAME (node);
       if (CLASSTYPE_TEMPLATE_ID_P (node))
-       template_info = CLASSTYPE_TEMPLATE_INFO (node);
+       template_info = TYPE_TEMPLATE_INFO (node);
     }
 
-  if (template_info != NULL)
+  /* In G++ 3.2, the name of the template parameter was used.  */
+  if (TREE_CODE (node) == TEMPLATE_TYPE_PARM 
+      && !abi_version_at_least (2))
+    G.need_abi_warning = true;
+
+  if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+      && abi_version_at_least (2))
+    write_template_param (node);
+  else if (template_info != NULL)
     /* Templated.  */
     {
       write_template_prefix (decl);
@@ -898,6 +914,7 @@ write_prefix (node)
 }
 
 /* <template-prefix> ::= <prefix> <template component>
+                     ::= <template-param>
                      ::= <substitution>  */
 
 static void
@@ -917,7 +934,7 @@ write_template_prefix (node)
   if (decl_is_template_id (decl, &template_info))
     template = TI_TEMPLATE (template_info);
   else if (CLASSTYPE_TEMPLATE_ID_P (type))
-    template = CLASSTYPE_TI_TEMPLATE (type);
+    template = TYPE_TI_TEMPLATE (type);
   else
     /* Oops, not a template.  */
     abort ();
@@ -952,8 +969,19 @@ write_template_prefix (node)
   if (find_substitution (substitution))
     return;
 
-  write_prefix (context);
-  write_unqualified_name (decl);
+  /* In G++ 3.2, the name of the template template parameter was used.  */
+  if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+      && !abi_version_at_least (2))
+    G.need_abi_warning = true;
+
+  if (TREE_CODE (TREE_TYPE (template)) == TEMPLATE_TEMPLATE_PARM
+      && abi_version_at_least (2))
+    write_template_param (TREE_TYPE (template));
+  else
+    {
+      write_prefix (context);
+      write_unqualified_name (decl);
+    }
 
   add_substitution (substitution);
 }
@@ -2168,20 +2196,29 @@ write_substitution (seq_id)
   write_char ('_');
 }
 
-/* Start mangling a new name or type.  */
+/* Start mangling ENTITY.  */
 
 static inline void
-start_mangling ()
+start_mangling (tree entity)
 {
+  G.entity = entity;
+  G.need_abi_warning = false;
   VARRAY_TREE_INIT (G.substitutions, 1, "mangling substitutions");
   obstack_free (&G.name_obstack, obstack_base (&G.name_obstack));
 }
 
-/* Done with mangling.  Return the generated mangled name.  */
+/* Done with mangling.  Return the generated mangled name.  If WARN is
+   true, and the name of G.entity will be mangled differently in a
+   future version of the ABI, issue a warning.  */
 
 static inline const char *
-finish_mangling ()
+finish_mangling (bool warn)
 {
+  if (warn_abi && warn && G.need_abi_warning)
+    warning ("the mangled name of `%D' will change in a future "
+            "version of GCC",
+            G.entity);
+
   /* Clear all the substitutions.  */
   G.substitutions = 0;
 
@@ -2216,7 +2253,7 @@ mangle_decl_string (decl)
 {
   const char *result;
 
-  start_mangling ();
+  start_mangling (decl);
 
   if (TREE_CODE (decl) == TYPE_DECL)
     write_type (TREE_TYPE (decl));
@@ -2243,7 +2280,7 @@ mangle_decl_string (decl)
        write_string (" *INTERNAL* ");
     }
 
-  result = finish_mangling ();
+  result = finish_mangling (/*warn=*/true);
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_decl_string = '%s'\n\n", result);
   return result;
@@ -2268,9 +2305,9 @@ mangle_type_string (type)
 {
   const char *result;
 
-  start_mangling ();
+  start_mangling (type);
   write_type (type);
-  result = finish_mangling ();
+  result = finish_mangling (/*warn=*/false);
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_type_string = '%s'\n\n", result);
   return result;
@@ -2298,7 +2335,7 @@ mangle_special_for_type (type, code)
 
   /* We don't have an actual decl here for the special component, so
      we can't just process the <encoded-name>.  Instead, fake it.  */
-  start_mangling ();
+  start_mangling (type);
 
   /* Start the mangling.  */
   write_string ("_Z");
@@ -2306,7 +2343,7 @@ mangle_special_for_type (type, code)
 
   /* Add the type.  */
   write_type (type);
-  result = finish_mangling ();
+  result = finish_mangling (/*warn=*/false);
 
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_special_for_type = %s\n\n", result);
@@ -2373,7 +2410,7 @@ mangle_ctor_vtbl_for_type (type, binfo)
 {
   const char *result;
 
-  start_mangling ();
+  start_mangling (type);
 
   write_string ("_Z");
   write_string ("TC");
@@ -2382,7 +2419,7 @@ mangle_ctor_vtbl_for_type (type, binfo)
   write_char ('_');
   write_type (BINFO_TYPE (binfo));
 
-  result = finish_mangling ();
+  result = finish_mangling (/*warn=*/false);
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_ctor_vtbl_for_type = %s\n\n", result);
   return get_identifier (result);
@@ -2406,7 +2443,7 @@ mangle_thunk (fn_decl, offset, vcall_offset)
 {
   const char *result;
   
-  start_mangling ();
+  start_mangling (fn_decl);
 
   write_string ("_Z");
   /* The <special-name> for virtual thunks is Tv, for non-virtual
@@ -2432,7 +2469,7 @@ mangle_thunk (fn_decl, offset, vcall_offset)
   /* Scoped name.  */
   write_encoding (fn_decl);
 
-  result = finish_mangling ();
+  result = finish_mangling (/*warn=*/false);
   if (DEBUG_MANGLE)
     fprintf (stderr, "mangle_thunk = %s\n\n", result);
   return get_identifier (result);
@@ -2484,7 +2521,7 @@ tree
 mangle_guard_variable (variable)
      tree variable;
 {
-  start_mangling ();
+  start_mangling (variable);
   write_string ("_ZGV");
   if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
     /* The name of a guard variable for a reference temporary should refer
@@ -2492,7 +2529,7 @@ mangle_guard_variable (variable)
     write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
   else
     write_name (variable, /*ignore_local_scope=*/0);
-  return get_identifier (finish_mangling ());
+  return get_identifier (finish_mangling (/*warn=*/false));
 }
 
 /* Return an identifier for the name of a temporary variable used to
@@ -2503,10 +2540,10 @@ tree
 mangle_ref_init_variable (variable)
      tree variable;
 {
-  start_mangling ();
+  start_mangling (variable);
   write_string ("_ZGR");
   write_name (variable, /*ignore_local_scope=*/0);
-  return get_identifier (finish_mangling ());
+  return get_identifier (finish_mangling (/*warn=*/false));
 }
 \f
 
index 607a08aff3c944afdc34fc961abf76bc46776ef1..65aa2a050bf7f9c71794c752ae33d27654ee87c3 100644 (file)
@@ -1565,6 +1565,21 @@ G++ will place the @code{A} base class of @code{C} at a non-zero offset;
 it should be placed at offset zero.  G++ mistakenly believes that the
 @code{A} data member of @code{B} is already at offset zero.
 
+@item
+Names of template functions whose types involve @code{typename} or
+template template parameters can be mangled incorrectly.
+
+@smallexample
+template <typename Q>
+void f(typename Q::X) @{@}
+
+template <template <typename> class Q>
+void f(typename Q<int>::X) @{@}
+@end smallexample
+
+@noindent
+Instantions of these templates may be mangled incorrectly.
+
 @end itemize
 
 @item -Wctor-dtor-privacy @r{(C++ only)}
index 412533c7d300f20a1b477e20ddfe3d67c83fa813..61622064b64d3cd9d4faef3f80220451172712b2 100644 (file)
@@ -1,3 +1,11 @@
+2002-10-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/8006
+       * g++.dg/abi/mangle9.C: New test.
+       * g++.dg/abi/mangle10.C: New test.
+       * g++.dg/abi/mangle11.C: New test.
+       * g++.dg/abi/mangle12.C: New test.
+
 2002-10-02  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/7188.
diff --git a/gcc/testsuite/g++.dg/abi/mangle10.C b/gcc/testsuite/g++.dg/abi/mangle10.C
new file mode 100644 (file)
index 0000000..d5782ba
--- /dev/null
@@ -0,0 +1,13 @@
+// { dg-options "-fabi-version=0" }
+
+template <template <typename> class Q>
+void f (typename Q<int>::X) {}
+
+template <typename Q>
+struct S {
+  typedef int X;
+};
+
+template void f<S> (int);
+
+// { dg-final { scan-assembler _Z1fI1SEvNT_IiE1XE } }
diff --git a/gcc/testsuite/g++.dg/abi/mangle11.C b/gcc/testsuite/g++.dg/abi/mangle11.C
new file mode 100644 (file)
index 0000000..f715117
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-options "-Wabi" }
+
+template <typename Q>
+void f (typename Q::X) {}
+
+struct S {
+  typedef int X;
+};
+
+template void f<S> (int); // { dg-warning "mangle" }
diff --git a/gcc/testsuite/g++.dg/abi/mangle12.C b/gcc/testsuite/g++.dg/abi/mangle12.C
new file mode 100644 (file)
index 0000000..772b58b
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-options "-Wabi" }
+
+template <template <typename> class Q>
+void f (typename Q<int>::X) {}
+
+template <typename Q>
+struct S {
+  typedef int X;
+};
+
+template void f<S> (int); // { dg-warning "mangle" }
diff --git a/gcc/testsuite/g++.dg/abi/mangle9.C b/gcc/testsuite/g++.dg/abi/mangle9.C
new file mode 100644 (file)
index 0000000..f3ededf
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options "-fabi-version=0" }
+
+template <typename Q>
+void f (typename Q::X) {}
+
+struct S {
+  typedef int X;
+};
+
+template void f<S> (int);
+
+// { dg-final { scan-assembler _Z1fI1SEvNT_1XE } }