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]

Re: [C++] template mangling fixes


Mark Mitchell <mark@codesourcery.com> writes:

  Mark>   If so, make those changes, and check in.

OK, I'm committing this:

---

This patch cleans up the logic for determining whether a type or decl
is a template instance, and in the process fixes a couple of bugs in
mangling of typename types and template template args (that reported
on 30 July by Larry Evans).  Also removes an unneeded static variable,
and cleans up comments.

	* mangle.c (DECL_TEMPLATE_ID_P): Remove.
	(CLASSTYEP_TEMPLATE_ID_P): Check template info, and context when
	ascertaining primaryness.
	(G): Remove template_args.
	(decl_is_template_id): New function.
	(write_encoding): Use decl_is_template_id.
	(write_name): Likewise.  Handle type_decls.  Get main variant of
	type decls.
	(write_nested_name): Likewise.
	(write_prefix): Likewise.
	(write_template_prefix): Likewise.
	(write_special_name_constructor): Remove defunct production from
	comment.
	(write_bare_function_type): Remove comment about absent parameter.
	(write_template_template_arg): Add missing grammar production to
	comment.



Index: mangle.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/mangle.c,v
retrieving revision 1.12
diff -c -p -r1.12 mangle.c
*** mangle.c	2000/07/02 18:44:52	1.12
--- mangle.c	2000/07/30 23:33:31
***************
*** 74,90 ****
  # define MANGLE_TRACE_TREE(FN, NODE)
  #endif
  
! /* Non-zero if NODE is a template-id.  */
! #define DECL_TEMPLATE_ID_P(NODE)				\
!   (DECL_LANG_SPECIFIC (NODE) != NULL 				\
!    && DECL_USE_TEMPLATE (NODE)					\
!    && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (NODE)))
! 
! /* Non-zero if NODE is a class template-id.  */
! #define CLASSTYPE_TEMPLATE_ID_P(NODE)				\
!   (TYPE_LANG_SPECIFIC (NODE) != NULL 				\
!    && CLASSTYPE_USE_TEMPLATE (NODE)				\
!    && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
  
  /* Things we only need one of.  This module is not reentrant.  */
  static struct globals
--- 74,91 ----
  # define MANGLE_TRACE_TREE(FN, NODE)
  #endif
  
! /* Non-zero if NODE is a class template-id.  We can't rely on
!    CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
!    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.  The logic here is
!    historical magic that apparently produces the right result.  */
! #define CLASSTYPE_TEMPLATE_ID_P(NODE)				      \
!   (TYPE_LANG_SPECIFIC (NODE) != NULL 				      \
!    && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL                          \
!    && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE))              \
!        || (TREE_CODE (CP_DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE (NODE))) \
!            == FUNCTION_DECL)))
  
  /* Things we only need one of.  This module is not reentrant.  */
  static struct globals
*************** static struct globals
*** 92,100 ****
    /* The name in which we're building the mangled name.  */
    struct obstack name_obstack;
  
-   /* The current innermost template args.  */
-   tree template_args;
- 
    /* An array of the current substitution candidates, in the order
       we've seen them.  */
    varray_type substitutions;
--- 93,98 ----
*************** integer_type_codes[itk_none] =
*** 136,141 ****
--- 134,141 ----
    'y'   /* itk_unsigned_long_long */
  };
  
+ static int decl_is_template_id PARAMS ((tree, tree*));
+ 
  /* Functions for handling substitutions.  */
  
  static inline tree canonicalize_for_substitution PARAMS ((tree));
*************** static tree mangle_special_for_type PARA
*** 228,233 ****
--- 228,277 ----
  #define write_unsigned_number(NUMBER) \
    write_number (NUMBER, /*unsigned_p=*/1, 10)
  
+ /* If DECL is a template instance, return non-zero and, if
+    TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
+    Otherwise return zero.  */
+ 
+ static int
+ decl_is_template_id (decl, template_info)
+      tree decl;
+      tree* template_info;
+ {
+   if (TREE_CODE (decl) == TYPE_DECL)
+     {
+       /* TYPE_DECLs are handled specially.  Look at its type to decide
+ 	 if this is a template instantiation.  */
+       tree type = TREE_TYPE (decl);
+ 
+       if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type))
+ 	{
+ 	  if (template_info != NULL)
+ 	    /* For a templated TYPE_DECL, the template info is hanging
+ 	       off the type.  */
+ 	    *template_info = CLASSTYPE_TEMPLATE_INFO (type);
+ 	  return 1;
+ 	}
+     } 
+   else
+     {
+       /* Check if this is a primary template.  */
+       if (DECL_LANG_SPECIFIC (decl) != NULL
+ 	  && DECL_USE_TEMPLATE (decl)
+ 	  && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
+ 	  && TREE_CODE (decl) != TEMPLATE_DECL)
+ 	{
+ 	  if (template_info != NULL)
+ 	    /* For most templated decls, the template info is hanging
+ 	       off the decl.  */
+ 	    *template_info = DECL_TEMPLATE_INFO (decl);
+ 	  return 1;
+ 	}
+     }
+ 
+   /* It's not a template id.  */
+   return 0;
+ }
+ 
  /* Produce debugging output of current substitution candidates.  */
  
  static void
*************** write_encoding (decl)
*** 591,602 ****
      {
        tree fn_type;
  
!       if (DECL_TEMPLATE_ID_P (decl))
  	fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
        else
  	fn_type = TREE_TYPE (decl);
  
!       write_bare_function_type (fn_type, DECL_TEMPLATE_ID_P (decl));
      }
  }
  
--- 635,646 ----
      {
        tree fn_type;
  
!       if (decl_is_template_id (decl, NULL))
  	fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
        else
  	fn_type = TREE_TYPE (decl);
  
!       write_bare_function_type (fn_type, decl_is_template_id (decl, NULL));
      }
  }
  
*************** write_name (decl)
*** 611,638 ****
  {
    tree context;
  
-   context = CP_DECL_CONTEXT (decl);
- 
    MANGLE_TRACE_TREE ("name", decl);
  
!   /* Decls in :: or ::std scope are treated specially.  */
!   if (context == global_namespace || DECL_NAMESPACE_STD_P (context))
      {
!       if (decl && DECL_TEMPLATE_ID_P (decl))
! 	{
! 	  /* Templated decls get an <unqualified-template-name>.  */
! 	  write_unscoped_template_name (DECL_TI_TEMPLATE (decl));
! 	  write_template_args (DECL_TI_ARGS (decl));
! 	}
!       else if (TREE_CODE (decl) == TYPE_DECL 
! 	       && CLASSTYPE_TEMPLATE_ID_P (TREE_TYPE (decl)))
! 	{
! 	  tree type;
  
! 	  /* Templated decls get an <unqualified-template-name>.  */
! 	  type = TREE_TYPE (decl);
! 	  write_unscoped_template_name (TYPE_TI_TEMPLATE (type));
! 	  write_template_args (TYPE_TI_ARGS (type));
  	}
        else
  	/* Everything else gets an <unqualified-name>.  */
--- 655,684 ----
  {
    tree context;
  
    MANGLE_TRACE_TREE ("name", decl);
  
!   if (TREE_CODE (decl) == TYPE_DECL)
      {
!       /* In case this is a typedef, fish out the corresponding
! 	 TYPE_DECL for the main variant.  */
!       decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
!       context = TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
!     }
!   else
!     context = (DECL_CONTEXT (decl) == NULL) ? NULL : CP_DECL_CONTEXT (decl);
  
!   /* Decls in :: or ::std scope are treated specially.  */
!   if (context == NULL 
!       || context == global_namespace 
!       || DECL_NAMESPACE_STD_P (context))
!     {
!       tree template_info;
!       /* Is this a template instance?  */
!       if (decl_is_template_id (decl, &template_info))
! 	{
! 	  /* Yes: use <unscoped-template-name>.  */
! 	  write_unscoped_template_name (TI_TEMPLATE (template_info));
! 	  write_template_args (TI_ARGS (template_info));
  	}
        else
  	/* Everything else gets an <unqualified-name>.  */
*************** static void
*** 696,701 ****
--- 742,749 ----
  write_nested_name (decl)
       tree decl;
  {
+   tree template_info;
+ 
    MANGLE_TRACE_TREE ("nested-name", decl);
  
    write_char ('N');
*************** write_nested_name (decl)
*** 710,727 ****
  	write_char ('K');
      }
  
!   if (DECL_TEMPLATE_ID_P (decl))
      {
        write_template_prefix (decl);
!       write_template_args (DECL_TI_ARGS (decl));
      }
-   else if (CLASSTYPE_TEMPLATE_ID_P (TREE_TYPE (decl)))
-     {
-       write_template_prefix (decl);
-       write_template_args (CLASSTYPE_TI_ARGS (TREE_TYPE (decl)));
-     }
    else
      {
        write_prefix (DECL_CONTEXT (decl));
        write_component (decl);
      }
--- 758,773 ----
  	write_char ('K');
      }
  
!   /* Is this a template instance?  */
!   if (decl_is_template_id (decl, &template_info))
      {
+       /* Yes, use <template-prefix>.  */
        write_template_prefix (decl);
!       write_template_args (TI_ARGS (template_info));
      }
    else
      {
+       /* No, just use <prefix>  */
        write_prefix (DECL_CONTEXT (decl));
        write_component (decl);
      }
*************** write_prefix (node)
*** 738,777 ****
       tree node;
  {
    tree decl;
!   tree type;
!   tree context;
  
    if (node == NULL
        || node == global_namespace)
      return;
  
-   MANGLE_TRACE_TREE ("prefix", node);
- 
-   decl = DECL_P (node) ? node : TYPE_NAME (node);
-   type = DECL_P (node) ? TREE_TYPE (node) : node;
-   context = CP_DECL_CONTEXT (decl);
- 
    if (find_substitution (node))
      return;
  
!   /* Check if this is a template-id.  For a template member, the
!      template info will be hanging off the decl.  */
!   if (DECL_TEMPLATE_ID_P (decl))
      {
!       write_template_prefix (decl);
!       write_template_args (DECL_TI_ARGS (decl));
      }
!   /* For a template class, the template info will be hanging off the
!      type.  */
!   else if (type && CLASSTYPE_TEMPLATE_ID_P (type))
      {
!       write_template_prefix (type);
!       write_template_args (CLASSTYPE_TI_ARGS (type));
      }
    else
      /* Not templated.  */
      {
!       write_prefix (context);
        write_component (decl);
      }
  
--- 784,825 ----
       tree node;
  {
    tree decl;
!   /* Non-NULL if NODE represents a template-id.  */
!   tree template_info = NULL;
! 
!   MANGLE_TRACE_TREE ("prefix", node);
  
    if (node == NULL
        || node == global_namespace)
      return;
  
    if (find_substitution (node))
      return;
  
!   if (DECL_P (node))
!     /* Node is a decl.  */
      {
!       decl = node;
!       decl_is_template_id (decl, &template_info);
      }
!   else
!     /* Node is a type.  */
!     {
!       decl = TYPE_NAME (node);
!       if (CLASSTYPE_TEMPLATE_ID_P (node))
! 	template_info = CLASSTYPE_TEMPLATE_INFO (node);
!     }
! 
!   if (template_info != NULL)
!     /* Templated.  */
      {
!       write_template_prefix (decl);
!       write_template_args (TI_ARGS (template_info));
      }
    else
      /* Not templated.  */
      {
!       write_prefix (CP_DECL_CONTEXT (decl));
        write_component (decl);
      }
  
*************** write_template_prefix (node)
*** 788,801 ****
    tree decl = DECL_P (node) ? node : TYPE_NAME (node);
    tree type = DECL_P (node) ? TREE_TYPE (node) : node;
    tree context = CP_DECL_CONTEXT (decl);
    tree template;
    tree substitution;
  
    MANGLE_TRACE_TREE ("template-prefix", node);
  
    /* Find the template decl.  */
!   if (DECL_TEMPLATE_ID_P (decl))
!     template = DECL_TI_TEMPLATE (decl);
    else if (CLASSTYPE_TEMPLATE_ID_P (type))
      template = CLASSTYPE_TI_TEMPLATE (type);
    else
--- 836,850 ----
    tree decl = DECL_P (node) ? node : TYPE_NAME (node);
    tree type = DECL_P (node) ? TREE_TYPE (node) : node;
    tree context = CP_DECL_CONTEXT (decl);
+   tree template_info;
    tree template;
    tree substitution;
  
    MANGLE_TRACE_TREE ("template-prefix", node);
  
    /* Find the template decl.  */
!   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);
    else
*************** write_identifier (identifier)
*** 997,1003 ****
       <special-name> ::= C1   # complete object constructor
                      ::= C2   # base object constructor
                      ::= C3   # complete object allocating constructor
-                     ::= C4   # base object allocating constructor  
  
     Currently, allocating constructors are never used. 
  
--- 1046,1051 ----
*************** write_bare_function_type (type, include_
*** 1436,1444 ****
  
  /* Write the mangled representation of a method parameter list of
     types given in PARM_LIST.  If METHOD_P is non-zero, the function is 
!    considered a non-static method, and the this parameter is omitted.
!    If VARARGS_P is non-zero, an additional token designating varargs
!    is appended.  */
  
  static void
  write_method_parms (parm_list, method_p)
--- 1484,1490 ----
  
  /* Write the mangled representation of a method parameter list of
     types given in PARM_LIST.  If METHOD_P is non-zero, the function is 
!    considered a non-static method, and the this parameter is omitted.  */
  
  static void
  write_method_parms (parm_list, method_p)
*************** write_template_template_arg (tree decl)
*** 1744,1749 ****
--- 1790,1796 ----
  /* Non-terminal <array-type>.  TYPE is an ARRAY_TYPE.  
  
       <array-type> ::= A [</dimension/ number>] _ </element/ type>  
+                   ::= A <expression> _ </element/ type>
  
       "Array types encode the dimension (number of elements) and the
       element type. For variable length arrays, the dimension (but not

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